KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > gettext > MOFileParser


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Nam Nguyen
28  */

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 JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.logging.Logger JavaDoc;
44
45 /**
46  * Parses Gettext MO files.
47  */

48 class MOFileParser extends GettextParser
49 {
50   private static final Logger JavaDoc 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 JavaDoc _charset;
64
65   MOFileParser(Path path)
66     throws IOException JavaDoc
67   {
68     init(path);
69   }
70
71   private void init(Path path)
72     throws IOException JavaDoc
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     // Ignore file format revision
85
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   /**
100    * Returns the gettext metadata.
101    */

102   private StringValue getMetadata()
103     throws IOException JavaDoc
104   {
105     _in.setPosition(_offsetTranslation);
106     int length = readInt();
107     _in.setPosition(readInt());
108
109     return readPluralForms(length).get(0);
110   }
111
112   /**
113    * Returns the gettext translations.
114    *
115    * @return translations from file, or null on error
116    */

117   HashMap JavaDoc<UnicodeValue, ArrayList JavaDoc<UnicodeValue>> readTranslations()
118     throws IOException JavaDoc
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     // Read in offsets of the original strings
128
for (int i = 0; i < _numberOfStrings; i++) {
129       // XXX: length of original strings not needed?
130
readInt();
131
132       originalOffsets[i] = readInt();
133
134       if (originalOffsets[i] <= 0)
135         return null;
136     }
137
138     _in.setPosition(_offsetTranslation);
139
140     // Read in lengths and offsets of the translated strings
141
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     // Read in the original strings
153
for (int i = 0; i < _numberOfStrings; i++) {
154       _in.setPosition(originalOffsets[i]);
155
156       originals[i] = readOriginalString();
157     }
158
159     HashMap JavaDoc<UnicodeValue, ArrayList JavaDoc<UnicodeValue>> map =
160             new HashMap JavaDoc<UnicodeValue, ArrayList JavaDoc<UnicodeValue>>();
161
162     // Read translated strings into the HashMap
163
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   /**
173    * Reads in a string until NULL or EOF encountered.
174    */

175   private UnicodeValue readOriginalString()
176     throws IOException JavaDoc
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   /**
188    * Reads in translated plurals forms that are separated by NULL.
189    */

190   private ArrayList JavaDoc<UnicodeValue> readPluralForms(int length)
191     throws IOException JavaDoc
192   {
193     ArrayList JavaDoc<UnicodeValue> list = new ArrayList JavaDoc<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 JavaDoc
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