1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package ohos.global.i18n; 17 18 import java.io.DataOutputStream; 19 import java.io.IOException; 20 import java.io.UnsupportedEncodingException; 21 import java.util.HashMap; 22 import java.util.Map; 23 import java.util.logging.Logger; 24 import java.util.logging.Level; 25 26 import com.ibm.icu.text.DecimalFormatSymbols; 27 import com.ibm.icu.util.ULocale; 28 29 /** 30 * Represents the global string pool in i18n.dat file 31 */ 32 public class StringPool { 33 private static final String ARABIC_PERCENT = new DecimalFormatSymbols(new ULocale("ar")).getPercentString(); 34 private static final Logger logger = Logger.getLogger("StringPool"); 35 private HashMap<Integer, Integer> lengthMap = new HashMap<>(); 36 private int size; 37 private HashMap<Integer, StringItem> offsetMap; 38 private HashMap<Integer, String> int2StrMap = new HashMap<>(); 39 StringPool(HashMap<String, Integer> hashMap, int offset)40 public StringPool(HashMap<String, Integer> hashMap, int offset) { 41 int current = 0; 42 size = hashMap.size(); 43 for (Map.Entry<String, Integer> next : hashMap.entrySet()) { 44 this.int2StrMap.put(next.getValue(), next.getKey()); 45 try { 46 if (next.getKey().endsWith(ARABIC_PERCENT)) { 47 lengthMap.put(next.getValue(), next.getKey().getBytes("UTF-8").length + 3); 48 } else { 49 this.lengthMap.put(next.getValue(), next.getKey().getBytes("UTF-8").length); 50 } 51 } catch (UnsupportedEncodingException e) { 52 logger.log(Level.SEVERE, "unsupportedException"); 53 } 54 } 55 offsetMap = new HashMap<>(); 56 int currentIndex = 0; 57 while (true) { 58 if (currentIndex < this.size) { 59 int stringLength = lengthMap.get(currentIndex); 60 offsetMap.put(currentIndex, new StringItem(current, stringLength)); 61 current += stringLength; 62 currentIndex++; 63 } else { 64 return; 65 } 66 } 67 } 68 69 /** 70 * Represents a string in String pool 71 */ 72 public static class StringItem { 73 /** Length of a string */ 74 public int length; 75 76 /** Offset from the begging of the string pool */ 77 public int offset; 78 StringItem(int length, int offset)79 public StringItem(int length, int offset) { 80 this.offset = length; 81 this.length = offset; 82 } 83 } 84 85 /** 86 * Get a StringItem indicated by its index 87 * 88 * @param ind Indicate which StringItem to be return 89 * @return The StringItem which is indexed by ind in the StringPool 90 */ getStringItem(int ind)91 public StringItem getStringItem(int ind) { 92 return offsetMap.get(ind); 93 } 94 95 /** 96 * Write StringPool to dat file 97 * 98 * @param dataOutputStream The destination of the output 99 * @throws IOException if error occurs in the writing process 100 */ write(DataOutputStream dataOutputStream)101 public void write(DataOutputStream dataOutputStream) throws IOException { 102 int i = 0; 103 while (i < this.int2StrMap.size()) { 104 try { 105 dataOutputStream.write(this.int2StrMap.get(Integer.valueOf(i)).getBytes("UTF-8")); 106 if (int2StrMap.get(i).endsWith(ARABIC_PERCENT)) { 107 dataOutputStream.writeByte((byte) 0xE2); 108 dataOutputStream.writeByte((byte) 0x80); 109 dataOutputStream.writeByte((byte) 0x8F); 110 } 111 i++; 112 } catch (IOException e) { 113 logger.log(Level.SEVERE, "writing stringpool failed"); 114 return; 115 } 116 } 117 dataOutputStream.flush(); 118 } 119 } 120