1 29 30 package com.caucho.quercus.lib.gettext; 31 32 import com.caucho.quercus.env.StringBuilderValue; 33 import com.caucho.quercus.env.StringValue; 34 import com.caucho.quercus.env.UnicodeValue; 35 import com.caucho.quercus.lib.gettext.expr.PluralExpr; 36 import com.caucho.util.L10N; 37 import com.caucho.vfs.Path; 38 import com.caucho.vfs.ReadStream; 39 40 import java.io.IOException ; 41 import java.util.ArrayList ; 42 import java.util.HashMap ; 43 import java.util.logging.Logger ; 44 45 48 class MOFileParser extends GettextParser 49 { 50 private static final Logger log 51 = Logger.getLogger(MOFileParser.class.getName()); 52 private static final L10N L = new L10N(MOFileParser.class); 53 54 private ReadStream _in; 55 private byte[] _tmpBuf = new byte[4]; 56 57 private boolean _isLittleEndian; 58 59 private int _numberOfStrings; 60 private int _offsetOriginal; 61 private int _offsetTranslation; 62 63 private String _charset; 64 65 MOFileParser(Path path) 66 throws IOException  67 { 68 init(path); 69 } 70 71 private void init(Path path) 72 throws IOException  73 { 74 _in = path.openRead(); 75 76 _isLittleEndian = true; 77 int magic = readInt(); 78 79 if (magic == 0xde120495) 80 _isLittleEndian = false; 81 else if (magic != 0x950412de) 82 return; 83 84 readInt(); 86 87 _numberOfStrings = readInt(); 88 _offsetOriginal = readInt(); 89 _offsetTranslation = readInt(); 90 91 if (_numberOfStrings < 0 || _offsetOriginal < 0 || _offsetTranslation < 0) 92 return; 93 94 StringValue metadata = getMetadata(); 95 _pluralExpr = PluralExpr.getPluralExpr(metadata); 96 _charset = getCharset(metadata); 97 } 98 99 102 private StringValue getMetadata() 103 throws IOException  104 { 105 _in.setPosition(_offsetTranslation); 106 int length = readInt(); 107 _in.setPosition(readInt()); 108 109 return readPluralForms(length).get(0); 110 } 111 112 117 HashMap <UnicodeValue, ArrayList <UnicodeValue>> readTranslations() 118 throws IOException  119 { 120 int[] originalOffsets = new int[_numberOfStrings]; 121 int[] translatedOffsets = new int[_numberOfStrings]; 122 int[] translatedLengths = new int[_numberOfStrings]; 123 UnicodeValue[] originals = new UnicodeValue[_numberOfStrings]; 124 125 _in.setPosition(_offsetOriginal); 126 127 for (int i = 0; i < _numberOfStrings; i++) { 129 readInt(); 131 132 originalOffsets[i] = readInt(); 133 134 if (originalOffsets[i] <= 0) 135 return null; 136 } 137 138 _in.setPosition(_offsetTranslation); 139 140 for (int i = 0; i < _numberOfStrings; i++) { 142 translatedLengths[i] = readInt(); 143 144 translatedOffsets[i] = readInt(); 145 146 if (translatedLengths[i] < 0 || translatedOffsets[i] <= 0) 147 return null; 148 } 149 150 _in.setEncoding(_charset); 151 152 for (int i = 0; i < _numberOfStrings; i++) { 154 _in.setPosition(originalOffsets[i]); 155 156 originals[i] = readOriginalString(); 157 } 158 159 HashMap <UnicodeValue, ArrayList <UnicodeValue>> map = 160 new HashMap <UnicodeValue, ArrayList <UnicodeValue>>(); 161 162 for (int i = 0; i < _numberOfStrings; i++) { 164 _in.setPosition(translatedOffsets[i]); 165 166 map.put(originals[i], readPluralForms(translatedLengths[i])); 167 } 168 169 return map; 170 } 171 172 175 private UnicodeValue readOriginalString() 176 throws IOException  177 { 178 StringBuilderValue sb = new StringBuilderValue(); 179 180 for (int ch = _in.readChar(); ch > 0; ch = _in.readChar()) { 181 sb.append((char)ch); 182 } 183 184 return sb; 185 } 186 187 190 private ArrayList <UnicodeValue> readPluralForms(int length) 191 throws IOException  192 { 193 ArrayList <UnicodeValue> list = new ArrayList <UnicodeValue>(); 194 StringBuilderValue sb = new StringBuilderValue(); 195 196 for (; length > 0; length--) { 197 int ch = _in.readChar(); 198 199 if (ch > 0) 200 sb.append((char)ch); 201 202 else if (ch == 0) { 203 list.add(sb); 204 sb = new StringBuilderValue(); 205 } 206 else 207 break; 208 } 209 210 list.add(sb); 211 return list; 212 } 213 214 private int readInt() 215 throws IOException  216 { 217 int len = _in.read(_tmpBuf); 218 219 if (len != 4) 220 return -1; 221 222 if (_isLittleEndian) { 223 return (_tmpBuf[0] & 0xff) | 224 (_tmpBuf[1] & 0xff) << 8 | 225 (_tmpBuf[2] & 0xff) << 16 | 226 _tmpBuf[3] << 24; 227 } 228 else { 229 return _tmpBuf[0] << 24 | 230 (_tmpBuf[1] & 0xff) << 16 | 231 (_tmpBuf[2] & 0xff) << 8 | 232 (_tmpBuf[3] & 0xff); 233 } 234 } 235 236 void close() 237 { 238 if (_in != null) 239 _in.close(); 240 } 241 } 242 | Popular Tags |