/ app / src / main / java / com / reandroid / arsc / item / SpecFlagsArray.java
SpecFlagsArray.java
  1  /*
  2    *  Copyright (C) 2022 github.com/REAndroid
  3    *
  4    *  Licensed under the Apache License, Version 2.0 (the "License");
  5    *  you may not use this file except in compliance with the License.
  6    *  You may obtain a copy of the License at
  7    *
  8    *      http://www.apache.org/licenses/LICENSE-2.0
  9    *
 10    * Unless required by applicable law or agreed to in writing, software
 11    * distributed under the License is distributed on an "AS IS" BASIS,
 12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13    * See the License for the specific language governing permissions and
 14    * limitations under the License.
 15    */
 16  package com.reandroid.arsc.item;
 17  
 18  import com.reandroid.arsc.base.Block;
 19  import com.reandroid.arsc.chunk.SpecBlock;
 20  import com.reandroid.arsc.io.BlockLoad;
 21  import com.reandroid.arsc.io.BlockReader;
 22  import com.reandroid.arsc.value.Entry;
 23  import com.reandroid.json.JSONArray;
 24  import com.reandroid.json.JSONConvert;
 25  import com.reandroid.json.JSONObject;
 26  
 27  import java.io.IOException;
 28  import java.util.AbstractList;
 29  
 30  public class SpecFlagsArray extends IntegerArrayBlock implements BlockLoad, JSONConvert<JSONArray> {
 31      private final IntegerItem entryCount;
 32      private AbstractList<SpecFlag> specFlagList;
 33      public SpecFlagsArray(IntegerItem entryCount) {
 34          super();
 35          this.entryCount = entryCount;
 36          this.entryCount.setBlockLoad(this);
 37          setBlockLoad(this);
 38      }
 39      public AbstractList<SpecFlag> listSpecFlags(){
 40          if(specFlagList==null){
 41              specFlagList = new AbstractList<SpecFlag>() {
 42                  @Override
 43                  public SpecFlag get(int i) {
 44                      return SpecFlagsArray.this.getFlag(i);
 45                  }
 46                  @Override
 47                  public int size() {
 48                      return SpecFlagsArray.this.size();
 49                  }
 50              };
 51          }
 52          return specFlagList;
 53      }
 54      public SpecFlag getFlag(int id){
 55          id = id & 0xffff;
 56          if(id >= size()){
 57              return null;
 58          }
 59          int offset = id * 4;
 60          return new SpecFlag(this, offset);
 61      }
 62      public void set(int entryId, int value){
 63          setFlag(entryId, value);
 64          refresh();
 65      }
 66      private void setFlag(int id, int flag){
 67          id = 0xffff & id;
 68          ensureArraySize(id+1);
 69          super.put(id, flag);
 70      }
 71      @Override
 72      public int get(int entryId){
 73          entryId = 0xffff & entryId;
 74          return super.get(entryId);
 75      }
 76      @Override
 77      public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
 78          if(sender==this.entryCount){
 79              super.setSize(entryCount.get());
 80          }
 81      }
 82      public void refresh(){
 83          entryCount.set(size());
 84      }
 85  
 86      public void merge(SpecFlagsArray specFlagsArray){
 87          if(specFlagsArray == null || specFlagsArray==this){
 88              return;
 89          }
 90          this.ensureArraySize(specFlagsArray.size());
 91          int[] comingValues = specFlagsArray.toArray();
 92          int[] existValues = this.toArray();
 93          for(int i=0; i<comingValues.length; i++){
 94              int valueComing = comingValues[i];
 95              if(valueComing == 0){
 96                  continue;
 97              }
 98              int value = existValues[i] | valueComing;
 99              put(i, value);
100          }
101          refresh();
102      }
103  
104      @Override
105      public JSONArray toJson() {
106          JSONArray jsonArray = new JSONArray();
107          int[] flagValues = toArray();
108          for(int i=0; i<flagValues.length; i++){
109              int value = flagValues[i];
110              if(value==0){
111                  continue;
112              }
113              JSONObject jsonObject = new JSONObject();
114              jsonObject.put(Entry.NAME_id, i);
115              jsonObject.put(SpecBlock.NAME_flag, value);
116              jsonArray.put(jsonObject);
117          }
118          if(jsonArray.length()==0){
119              return null;
120          }
121          return jsonArray;
122      }
123      @Override
124      public void fromJson(JSONArray json) {
125          if(json==null || json.length()==0){
126              setSize(0);
127              refresh();
128              return;
129          }
130          int length = json.length();
131          length = length-1;
132          // to minimise calling new array creation during ensureSize,
133          // start from last entry
134          flagFromJson(json.getJSONObject(length));
135  
136          for(int i=0;i<length;i++){
137              flagFromJson(json.getJSONObject(i));
138          }
139          refresh();
140      }
141      private void flagFromJson(JSONObject jsonObject){
142          int id = jsonObject.getInt(Entry.NAME_id);
143          int flag = jsonObject.getInt(SpecBlock.NAME_flag);
144          setFlag(id, flag);
145      }
146  }