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 }