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 POFileParser extends GettextParser 49 { 50 private static final Logger log 51 = Logger.getLogger(POFileParser.class.getName()); 52 private static final L10N L = new L10N(POFileParser.class); 53 54 private ReadStream _in; 55 56 private static final int MSGID = 256; 58 private static final int MSGID_PLURAL = 257; 59 private static final int MSGSTR = 258; 60 61 private static final int UNKNOWN = 260; 62 63 private int _peekChar; 64 private UnicodeValue _string; 65 66 POFileParser(Path path) 67 throws IOException  68 { 69 init(path); 70 } 71 72 void init(Path path) 73 throws IOException  74 { 75 _in = path.openRead(); 76 _peekChar = -1; 77 78 StringValue metadata = getMetadata(); 79 80 _pluralExpr = PluralExpr.getPluralExpr(metadata); 81 _in.setEncoding(getCharset(metadata)); 82 } 83 84 private StringValue getMetadata() 85 throws IOException  86 { 87 StringValue metadata = null; 88 89 int token = readToken(); 90 91 while (token >= 0 && token != UNKNOWN) { 92 if (token == MSGID && _string.length() == 0) { 93 94 if (readToken() == MSGSTR) 95 metadata = _string; 96 97 break; 98 } 99 } 100 101 _peekChar = -1; 102 _in.setPosition(0); 103 104 return metadata; 105 } 106 107 112 HashMap <UnicodeValue, ArrayList <UnicodeValue>> readTranslations() 113 throws IOException  114 { 115 HashMap <UnicodeValue, ArrayList <UnicodeValue>> translations = 116 new HashMap <UnicodeValue, ArrayList <UnicodeValue>>(); 117 118 int token = readToken(); 119 120 while (token >= 0) { 121 if (token != MSGID) 122 return null; 123 124 UnicodeValue msgid = _string; 125 126 token = readToken(); 127 if (token == MSGID_PLURAL) 128 token = readToken(); 129 130 ArrayList <UnicodeValue> msgstrs = new ArrayList <UnicodeValue>(); 131 132 for (; token == MSGSTR; token = readToken()) { 133 msgstrs.add(_string); 134 } 135 136 translations.put(msgid, msgstrs); 137 } 138 139 return translations; 140 } 141 142 private int readToken() 143 throws IOException  144 { 145 int ch = skipWhitespace(); 146 147 switch (ch) { 148 case '#': 149 skipLine(); 150 return readToken(); 151 152 case 'm': 153 if (read() == 's' && 154 read() == 'g') { 155 return readMsgToken(); 156 } 157 else 158 return UNKNOWN; 159 160 case -1: 161 return -1; 162 163 default: 164 return UNKNOWN; 165 } 166 } 167 168 private int readMsgToken() 169 throws IOException  170 { 171 int ch = read(); 172 173 switch (ch) { 174 case 'i': 175 if (read() == 'd') 176 return readMsgidToken(); 177 else 178 return UNKNOWN; 179 180 case 's': 181 if (read() == 't' && 182 read() == 'r') 183 return readMsgstrToken(); 184 else 185 return UNKNOWN; 186 187 default: 188 return UNKNOWN; 189 } 190 } 191 192 private int readMsgidToken() 193 throws IOException  194 { 195 int token; 196 int ch = skipWhitespace(); 197 198 if (ch == '_') { 199 if (read() == 'p' && 200 read() == 'l' && 201 read() == 'u' && 202 read() == 'r' && 203 read() == 'a' && 204 read() == 'l') { 205 token = MSGID_PLURAL; 206 207 ch = skipWhitespace(); 208 } 209 else 210 return UNKNOWN; 211 } 212 else 213 token = MSGID; 214 215 if (ch != '"') 216 return UNKNOWN; 217 218 return readString(token); 219 } 220 221 private int readMsgstrToken() 222 throws IOException  223 { 224 int ch = skipWhitespace(); 225 226 if (ch == '[') { 227 ch = read(); 228 229 while (ch >= 0 && ch != ']') { 230 ch = read(); 231 } 232 233 ch = skipWhitespace(); 234 } 235 236 if (ch != '"') 237 return UNKNOWN; 238 239 return readString(MSGSTR); 240 } 241 242 245 private int readString(int token) 246 throws IOException  247 { 248 return readString(new StringBuilderValue(), token); 249 } 250 251 254 private int readString(StringBuilderValue sb, int token) 255 throws IOException  256 { 257 for (int ch = read(); ch != '"'; ch = read()) { 258 switch (ch) { 259 case '\\': 260 ch = read(); 261 switch (ch) { 262 case 'n': 263 sb.append('\n'); 264 break; 265 case 'r': 266 sb.append('\r'); 267 break; 268 case 't': 269 sb.append('\t'); 270 break; 271 case '\r': 272 ch = read(); 273 if (ch != '\n') 274 _peekChar = ch; 275 break; 276 case '\n': 277 break; 278 default: 279 _peekChar = ch; 280 sb.append('\\'); 281 } 282 break; 283 284 case -1: 285 return UNKNOWN; 286 287 default: 288 sb.append((char)ch); 289 } 290 } 291 292 294 int ch = skipWhitespace(); 295 296 if (ch == '"') 297 return readString(sb, token); 298 else 299 _peekChar = ch; 300 301 _string = sb; 302 return token; 303 } 304 305 private int read() 306 throws IOException  307 { 308 if (_peekChar >= 0) { 309 int swap = _peekChar; 310 _peekChar = -1; 311 return swap; 312 } 313 314 return _in.readChar(); 315 } 316 317 private void skipLine() 318 throws IOException  319 { 320 int ch = read(); 321 322 while (ch >= 0) { 323 switch (ch) { 324 case '\r': 325 ch = read(); 326 327 if (ch != '\n') 328 _peekChar = ch; 329 330 return; 331 332 case '\n': 333 return; 334 } 335 336 ch = read(); 337 } 338 } 339 340 private int skipWhitespace() 341 throws IOException  342 { 343 while (true) { 344 int ch = read(); 345 346 switch (ch) { 347 case ' ': 348 case '\r': 349 case '\n': 350 case '\t': 351 continue; 352 default: 353 return ch; 354 } 355 } 356 } 357 358 void close() 359 { 360 if (_in != null) 361 _in.close(); 362 } 363 } 364 | Popular Tags |