/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.reandroid.arsc.pool; import com.reandroid.arsc.array.StringArray; import com.reandroid.arsc.array.StyleArray; import com.reandroid.arsc.base.Block; import com.reandroid.arsc.chunk.Chunk; import com.reandroid.arsc.group.StringGroup; import com.reandroid.arsc.header.StringPoolHeader; import com.reandroid.arsc.io.BlockLoad; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.*; import com.reandroid.json.JSONArray; import com.reandroid.json.JSONConvert; import java.io.IOException; import java.util.*; public abstract class StringPool extends Chunk implements BlockLoad, JSONConvert, Comparator { private final StringArray mArrayStrings; private final StyleArray mArrayStyles; private final Map> mUniqueMap; StringPool(boolean is_utf8){ super(new StringPoolHeader(), 4); IntegerArray offsetStrings = new IntegerArray(); IntegerArray offsetStyles = new IntegerArray(); StringPoolHeader header = getHeaderBlock(); this.mArrayStrings = newInstance( offsetStrings, header.getCountStrings(), header.getStartStrings(), is_utf8); this.mArrayStyles = new StyleArray( offsetStyles, header.getCountStyles(), header.getStartStyles()); addChild(offsetStrings); addChild(offsetStyles); addChild(mArrayStrings); addChild(mArrayStyles); setUtf8(is_utf8, false); header.getFlagUtf8().setBlockLoad(this); mUniqueMap = new HashMap<>(); } public List toStringList(){ return getStringsArray().toStringList(); } public void addStrings(Collection stringList){ if(stringList==null || stringList.size()==0){ return; } Set uniqueSet; if(stringList instanceof HashSet){ uniqueSet=(HashSet)stringList; }else { uniqueSet=new HashSet<>(stringList); } refreshUniqueIdMap(); Set keySet=mUniqueMap.keySet(); for(String key:keySet){ uniqueSet.remove(key); } List sortedList=new ArrayList<>(stringList); sortedList.sort(this); insertStringList(sortedList); } private void insertStringList(List stringList){ StringArray stringsArray = getStringsArray(); int initialSize=stringsArray.childesCount(); stringsArray.ensureSize(initialSize + stringList.size()); int size=stringsArray.childesCount(); int j=0; for (int i=initialSize;i insertStrings(List stringList){ Map results=new HashMap<>(); StringArray stringsArray = getStringsArray(); int initialSize=stringsArray.childesCount(); stringsArray.ensureSize(initialSize + stringList.size()); int size=stringsArray.childesCount(); int j=0; for (int i=initialSize;i group= getOrCreateGroup(str); group.add(item); } } public List removeUnusedStrings(){ return getStringsArray().removeUnusedStrings(); } public List listUnusedStrings(){ return getStringsArray().listUnusedStrings(); } public Collection listStrings(){ return getStringsArray().listItems(); } public StyleArray getStyleArray(){ return mArrayStyles; } public StringArray getStringsArray(){ return mArrayStrings; } public void removeReferences(Collection referenceList){ if(referenceList==null){ return; } for(ReferenceItem ref:referenceList){ removeReference(ref); } } public boolean removeReference(ReferenceItem ref){ if(ref==null){ return false; } T item=get(ref.get()); if(item!=null){ return item.removeReference(ref); } return false; } public void addReference(ReferenceItem ref){ if(ref==null){ return; } T item=get(ref.get()); if(item!=null){ item.addReference(ref); } } public void addReferences(Collection referenceList){ if(referenceList==null){ return; } for(ReferenceItem ref:referenceList){ addReference(ref); } } public boolean contains(String str){ return mUniqueMap.containsKey(str); } public final T get(int index){ return mArrayStrings.get(index); } public final StringGroup get(String str){ return mUniqueMap.get(str); } public T getOrCreate(String str){ StringGroup group=getOrCreateGroup(str); T[] items=group.getItems(); if(items.length==0){ T t=createNewString(str); group.add(t); items=group.getItems(); } return items[0]; } private StringGroup getOrCreateGroup(String str){ StringGroup group=get(str); if(group!=null){ return group; } group=new StringGroup<>(mArrayStrings, str); mUniqueMap.put(str, group); return group; } private T createNewString(String str){ T item=mArrayStrings.createNext(); item.set(str); getHeaderBlock().getCountStrings().set(mArrayStrings.childesCount()); return item; } public final StyleItem getStyle(int index){ return mArrayStyles.get(index); } public final int countStrings(){ return mArrayStrings.childesCount(); } public final int countStyles(){ return mArrayStyles.childesCount(); } public final T[] getStrings(){ return mArrayStrings.getChildes(); } public final StyleItem[] getStyles(){ return mArrayStyles.getChildes(); } public void setUtf8(boolean is_utf8){ setUtf8(is_utf8, true); } public final void setSorted(boolean sorted){ ShortItem flagSorted = getHeaderBlock().getFlagSorted(); if(sorted){ flagSorted.set(FLAG_SORTED); }else { flagSorted.set((short)0); } } private void setUtf8(boolean is_utf8, boolean updateAll){ ShortItem flagUtf8 = getHeaderBlock().getFlagUtf8(); boolean old = isUtf8Flag(); if(is_utf8){ flagUtf8.set(UTF8_FLAG_VALUE); }else { flagUtf8.set((short) 0); } if(!updateAll || old == isUtf8Flag()){ return; } mArrayStrings.setUtf8(is_utf8); } private boolean isUtf8Flag(){ return (getHeaderBlock().getFlagUtf8().get() & FLAG_UTF8) !=0; } abstract StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8); @Override protected void onChunkRefreshed() { mArrayStrings.refreshCountAndStart(); mArrayStyles.refreshCountAndStart(); } @Override public void onChunkLoaded() { refreshUniqueIdMap(); } @Override public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { if(sender == getHeaderBlock().getFlagUtf8()){ mArrayStrings.setUtf8(isUtf8Flag()); } } @Override public JSONArray toJson() { return getStringsArray().toJson(); } //Only for styled strings @Override public void fromJson(JSONArray json) { if(json==null){ return; } JsonStringPoolHelper helper=new JsonStringPoolHelper<>(this); helper.loadStyledStrings(json); refresh(); } @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } private static final short UTF8_FLAG_VALUE=0x0100; private static final short FLAG_UTF8 = 0x0100; private static final short FLAG_SORTED = 0x0100; }