FixedLengthString.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.io.BlockReader; 19 import com.reandroid.utils.StringsUtil; 20 21 import java.nio.charset.StandardCharsets; 22 23 public class FixedLengthString extends StringItem { 24 private final int bytesLength; 25 public FixedLengthString(int bytesLength){ 26 super(true); 27 this.bytesLength = bytesLength; 28 setBytesLength(bytesLength); 29 } 30 @Override 31 protected byte[] encodeString(String text){ 32 if(text == null){ 33 return new byte[bytesLength]; 34 } 35 byte[] bytes = getUtf16Bytes(text); 36 byte[] results = new byte[this.bytesLength]; 37 int length = bytes.length; 38 if(length > this.bytesLength){ 39 length = this.bytesLength; 40 } 41 System.arraycopy(bytes, 0, results, 0, length); 42 return results; 43 } 44 @Override 45 protected String decodeString(byte[] bytes){ 46 return decodeUtf16Bytes(bytes); 47 } 48 @Override 49 public StyleItem getOrCreateStyle(){ 50 return null; 51 } 52 @Override 53 int calculateReadLength(BlockReader reader){ 54 return bytesLength; 55 } 56 57 @Override 58 protected void onStringChanged(String old, String text) { 59 } 60 61 @Override 62 public int compareTo(StringItem stringItem){ 63 if(stringItem == null){ 64 return -1; 65 } 66 return StringsUtil.compareStrings(get(), stringItem.get()); 67 } 68 @Override 69 public String toString(){ 70 return "FIXED-" + bytesLength + " {" + get() + "}"; 71 } 72 private static String decodeUtf16Bytes(byte[] bytes){ 73 if(isNullBytes(bytes)){ 74 return null; 75 } 76 int length = getEndNullPosition(bytes); 77 return new String(bytes,0, length, StandardCharsets.UTF_16LE); 78 } 79 private static int getEndNullPosition(byte[] bytes){ 80 int length = bytes.length; 81 int result = 0; 82 boolean found = false; 83 for(int i = 1; i < length; i++){ 84 byte b0 = bytes[i - 1]; 85 byte b1 = bytes[i]; 86 if(b0 == 0 && b1 == 0){ 87 if(!found){ 88 result = i; 89 found = true; 90 }else if(result<i-1){ 91 return result; 92 } 93 }else { 94 found = false; 95 } 96 } 97 if(!found){ 98 return length; 99 } 100 return result; 101 } 102 }