]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/text/UnicodeDecompressor.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / text / UnicodeDecompressor.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2007, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 \r
8 package com.ibm.icu.text;\r
9 \r
10 /**\r
11 * A decompression engine implementing the Standard Compression Scheme\r
12 * for Unicode (SCSU) as outlined in <A\r
13 * HREF="http://www.unicode.org/unicode/reports/tr6">Unicode Technical\r
14 * Report #6</A>.\r
15 *\r
16 * <P><STRONG>USAGE</STRONG></P>\r
17 *\r
18 * <P>The static methods on <TT>UnicodeDecompressor</TT> may be used in a\r
19 * straightforward manner to decompress simple strings:</P>\r
20 *\r
21 * <PRE>\r
22 *  byte [] compressed = ... ; // get compressed bytes from somewhere\r
23 *  String result = UnicodeDecompressor.decompress(compressed);\r
24 * </PRE>\r
25 *\r
26 * <P>The static methods have a fairly large memory footprint.\r
27 * For finer-grained control over memory usage, \r
28 * <TT>UnicodeDecompressor</TT> offers more powerful APIs allowing\r
29 * iterative decompression:</P>\r
30 *\r
31 * <PRE>\r
32 *  // Decompress an array "bytes" of length "len" using a buffer of 512 chars\r
33 *  // to the Writer "out"\r
34 *\r
35 *  UnicodeDecompressor myDecompressor         = new UnicodeDecompressor();\r
36 *  final static int    BUFSIZE                = 512;\r
37 *  char []             charBuffer             = new char [ BUFSIZE ];\r
38 *  int                 charsWritten           = 0;\r
39 *  int []              bytesRead              = new int [1];\r
40 *  int                 totalBytesDecompressed = 0;\r
41 *  int                 totalCharsWritten      = 0;\r
42 *\r
43 *  do {\r
44 *    // do the decompression\r
45 *    charsWritten = myDecompressor.decompress(bytes, totalBytesDecompressed, \r
46 *                                             len, bytesRead,\r
47 *                                             charBuffer, 0, BUFSIZE);\r
48 *\r
49 *    // do something with the current set of chars\r
50 *    out.write(charBuffer, 0, charsWritten);\r
51 *\r
52 *    // update the no. of bytes decompressed\r
53 *    totalBytesDecompressed += bytesRead[0];\r
54 *\r
55 *    // update the no. of chars written\r
56 *    totalCharsWritten += charsWritten;\r
57 *\r
58 *  } while(totalBytesDecompressed < len);\r
59 *\r
60 *  myDecompressor.reset(); // reuse decompressor\r
61 * </PRE>\r
62 *\r
63 * <P>Decompression is performed according to the standard set forth in \r
64 * <A HREF="http://www.unicode.org/unicode/reports/tr6">Unicode Technical \r
65 * Report #6</A></P>\r
66 *\r
67 * @see UnicodeCompressor\r
68 *\r
69 * @author Stephen F. Booth\r
70 * @stable ICU 2.4\r
71 */\r
72 public final class UnicodeDecompressor implements SCSU\r
73 {\r
74     //==========================\r
75     // Instance variables\r
76     //==========================\r
77     \r
78     /** Alias to current dynamic window */\r
79     private int       fCurrentWindow   = 0;\r
80 \r
81     /** Dynamic compression window offsets */\r
82     private int []    fOffsets         = new int [ NUMWINDOWS ];\r
83 \r
84     /** Current compression mode */\r
85     private int       fMode            = SINGLEBYTEMODE;\r
86 \r
87     /** Size of our internal buffer */\r
88     private final static int BUFSIZE   = 3;\r
89 \r
90     /** Internal buffer for saving state */\r
91     private byte []   fBuffer          = new byte [BUFSIZE];\r
92 \r
93     /** Number of characters in our internal buffer */\r
94     private int       fBufferLength    = 0;\r
95     \r
96 \r
97     /**\r
98      * Create a UnicodeDecompressor.\r
99      * Sets all windows to their default values.\r
100      * @see #reset\r
101      * @stable ICU 2.4\r
102      */\r
103     public UnicodeDecompressor()\r
104     {\r
105     reset();              // initialize to defaults\r
106     }\r
107 \r
108     /**\r
109      * Decompress a byte array into a String.\r
110      * @param buffer The byte array to decompress.\r
111      * @return A String containing the decompressed characters.\r
112      * @see #decompress(byte [], int, int)\r
113      * @stable ICU 2.4\r
114      */\r
115     public static String decompress(byte [] buffer)\r
116     {\r
117     char [] buf = decompress(buffer, 0, buffer.length);\r
118     return new String(buf);\r
119     }\r
120 \r
121     /**\r
122      * Decompress a byte array into a Unicode character array.\r
123      * @param buffer The byte array to decompress.\r
124      * @param start The start of the byte run to decompress.\r
125      * @param limit The limit of the byte run to decompress.\r
126      * @return A character array containing the decompressed bytes.\r
127      * @see #decompress(byte [])\r
128      * @stable ICU 2.4\r
129      */\r
130     public static char [] decompress(byte [] buffer,\r
131                      int start,\r
132                      int limit)\r
133     {\r
134     UnicodeDecompressor comp = new UnicodeDecompressor();\r
135 \r
136     // use a buffer we know will never overflow\r
137     // in the worst case, each byte will decompress\r
138     // to a surrogate pair (buffer must be at least 2 chars)\r
139     int len = Math.max(2, 2 * (limit - start));\r
140     char [] temp = new char [len];\r
141 \r
142     int charCount = comp.decompress(buffer, start, limit, null, \r
143                     temp, 0, len);\r
144 \r
145     char [] result = new char [charCount];\r
146     System.arraycopy(temp, 0, result, 0, charCount);\r
147     return result;\r
148     }\r
149     \r
150     /**\r
151      * Decompress a byte array into a Unicode character array.\r
152      *\r
153      * This function will either completely fill the output buffer, \r
154      * or consume the entire input.  \r
155      *\r
156      * @param byteBuffer The byte buffer to decompress.\r
157      * @param byteBufferStart The start of the byte run to decompress.\r
158      * @param byteBufferLimit The limit of the byte run to decompress.\r
159      * @param bytesRead A one-element array.  If not null, on return\r
160      * the number of bytes read from byteBuffer.\r
161      * @param charBuffer A buffer to receive the decompressed data. \r
162      * This buffer must be at minimum two characters in size.\r
163      * @param charBufferStart The starting offset to which to write \r
164      * decompressed data.\r
165      * @param charBufferLimit The limiting offset for writing \r
166      * decompressed data.\r
167      * @return The number of Unicode characters written to charBuffer.\r
168      * @stable ICU 2.4\r
169      */\r
170     public int decompress(byte []    byteBuffer,\r
171               int        byteBufferStart,\r
172               int        byteBufferLimit,\r
173               int []     bytesRead,\r
174               char []    charBuffer,\r
175               int        charBufferStart,\r
176               int        charBufferLimit)\r
177     {\r
178     // the current position in the source byte buffer\r
179     int bytePos      = byteBufferStart;\r
180     \r
181     // the current position in the target char buffer\r
182     int ucPos        = charBufferStart;\r
183         \r
184         // the current byte from the source buffer\r
185     int aByte        = 0x00;\r
186 \r
187 \r
188     // charBuffer must be at least 2 chars in size\r
189     if(charBuffer.length < 2 || (charBufferLimit - charBufferStart) < 2)\r
190         throw new IllegalArgumentException("charBuffer.length < 2");\r
191     \r
192     // if our internal buffer isn't empty, flush its contents\r
193     // to the output buffer before doing any more decompression\r
194     if(fBufferLength > 0) {\r
195 \r
196         int newBytes = 0;\r
197 \r
198         // fill the buffer completely, to guarantee one full character\r
199         if(fBufferLength != BUFSIZE) {\r
200         newBytes = fBuffer.length - fBufferLength;\r
201 \r
202         // verify there are newBytes bytes in byteBuffer\r
203         if(byteBufferLimit - byteBufferStart < newBytes)\r
204             newBytes = byteBufferLimit - byteBufferStart;\r
205 \r
206         System.arraycopy(byteBuffer, byteBufferStart, \r
207                  fBuffer, fBufferLength, newBytes);\r
208         }\r
209 \r
210         // reset buffer length to 0 before recursive call\r
211         fBufferLength = 0;\r
212 \r
213         // call self recursively to decompress the buffer\r
214         int count = decompress(fBuffer, 0, fBuffer.length, null,\r
215                    charBuffer, charBufferStart, \r
216                    charBufferLimit);\r
217 \r
218         // update the positions into the arrays\r
219         ucPos += count;\r
220         bytePos += newBytes;\r
221     }\r
222 \r
223         // the main decompression loop\r
224     mainLoop:\r
225     while(bytePos < byteBufferLimit && ucPos < charBufferLimit) {\r
226         switch(fMode) {  \r
227         case SINGLEBYTEMODE:\r
228         // single-byte mode decompression loop\r
229         singleByteModeLoop:\r
230         while(bytePos < byteBufferLimit && ucPos < charBufferLimit) {\r
231         aByte = byteBuffer[bytePos++] & 0xFF;\r
232         switch(aByte) {\r
233             // All bytes from 0x80 through 0xFF are remapped\r
234             // to chars or surrogate pairs according to the\r
235             // currently active window\r
236         case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: \r
237         case 0x85: case 0x86: case 0x87: case 0x88: case 0x89:\r
238         case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E:\r
239         case 0x8F: case 0x90: case 0x91: case 0x92: case 0x93:\r
240         case 0x94: case 0x95: case 0x96: case 0x97: case 0x98:\r
241         case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D:\r
242         case 0x9E: case 0x9F: case 0xA0: case 0xA1: case 0xA2:\r
243         case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7:\r
244         case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC:\r
245         case 0xAD: case 0xAE: case 0xAF: case 0xB0: case 0xB1:\r
246         case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6:\r
247         case 0xB7: case 0xB8: case 0xB9: case 0xBA: case 0xBB:\r
248         case 0xBC: case 0xBD: case 0xBE: case 0xBF: case 0xC0:\r
249         case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5:\r
250         case 0xC6: case 0xC7: case 0xC8: case 0xC9: case 0xCA:\r
251         case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:\r
252         case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4:\r
253         case 0xD5: case 0xD6: case 0xD7: case 0xD8: case 0xD9:\r
254         case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE:\r
255         case 0xDF: case 0xE0: case 0xE1: case 0xE2: case 0xE3:\r
256         case 0xE4: case 0xE5: case 0xE6: case 0xE7: case 0xE8:\r
257         case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED:\r
258         case 0xEE: case 0xEF: case 0xF0: case 0xF1: case 0xF2:\r
259         case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:\r
260         case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC:\r
261         case 0xFD: case 0xFE: case 0xFF: \r
262             // For offsets <= 0xFFFF, convert to a single char\r
263             // by adding the window's offset and subtracting\r
264             // the generic compression offset\r
265             if(fOffsets[ fCurrentWindow ] <= 0xFFFF) {\r
266             charBuffer[ucPos++] = (char) \r
267                 (aByte + fOffsets[ fCurrentWindow ] \r
268                  - COMPRESSIONOFFSET);\r
269             }\r
270             // For offsets > 0x10000, convert to a surrogate pair by \r
271             // normBase = window's offset - 0x10000\r
272             // high surr. = 0xD800 + (normBase >> 10)\r
273             // low  surr. = 0xDC00 + (normBase & 0x3FF) + (byte & 0x7F)\r
274             else {\r
275             // make sure there is enough room to write\r
276             // both characters \r
277             // if not, save state and break out\r
278             if((ucPos + 1) >= charBufferLimit) {\r
279                 --bytePos;\r
280                 System.arraycopy(byteBuffer, bytePos,\r
281                          fBuffer, 0, \r
282                          byteBufferLimit - bytePos);\r
283                 fBufferLength = byteBufferLimit - bytePos;\r
284                 bytePos += fBufferLength;\r
285                 break mainLoop; \r
286             }\r
287             \r
288             int normalizedBase = fOffsets[ fCurrentWindow ] \r
289                 - 0x10000;\r
290             charBuffer[ucPos++] = (char) \r
291                 (0xD800 + (normalizedBase >> 10));\r
292             charBuffer[ucPos++] = (char) \r
293                 (0xDC00 + (normalizedBase & 0x3FF)+(aByte & 0x7F));\r
294             }\r
295             break;\r
296 \r
297             // bytes from 0x20 through 0x7F are treated as ASCII and\r
298             // are remapped to chars by padding the high byte\r
299             // (this is the same as quoting from static window 0)\r
300             // NUL (0x00), HT (0x09), CR (0x0A), LF (0x0D) \r
301             // are treated as ASCII as well\r
302         case 0x00: case 0x09: case 0x0A: case 0x0D:\r
303         case 0x20: case 0x21: case 0x22: case 0x23: case 0x24:\r
304         case 0x25: case 0x26: case 0x27: case 0x28: case 0x29:\r
305         case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E:\r
306         case 0x2F: case 0x30: case 0x31: case 0x32: case 0x33:\r
307         case 0x34: case 0x35: case 0x36: case 0x37: case 0x38:\r
308         case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D:\r
309         case 0x3E: case 0x3F: case 0x40: case 0x41: case 0x42:\r
310         case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:\r
311         case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C:\r
312         case 0x4D: case 0x4E: case 0x4F: case 0x50: case 0x51:\r
313         case 0x52: case 0x53: case 0x54: case 0x55: case 0x56:\r
314         case 0x57: case 0x58: case 0x59: case 0x5A: case 0x5B:\r
315         case 0x5C: case 0x5D: case 0x5E: case 0x5F: case 0x60:\r
316         case 0x61: case 0x62: case 0x63: case 0x64: case 0x65:\r
317         case 0x66: case 0x67: case 0x68: case 0x69: case 0x6A:\r
318         case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:\r
319         case 0x70: case 0x71: case 0x72: case 0x73: case 0x74:\r
320         case 0x75: case 0x76: case 0x77: case 0x78: case 0x79:\r
321         case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E:\r
322         case 0x7F: \r
323             charBuffer[ucPos++] = (char) aByte;\r
324             break;\r
325 \r
326             // quote unicode\r
327         case SQUOTEU:\r
328             // verify we have two bytes following tag\r
329             // if not, save state and break out\r
330             if( (bytePos + 1) >= byteBufferLimit ) {\r
331             --bytePos;\r
332             System.arraycopy(byteBuffer, bytePos,\r
333                      fBuffer, 0, \r
334                      byteBufferLimit - bytePos);\r
335             fBufferLength = byteBufferLimit - bytePos;\r
336             bytePos += fBufferLength;\r
337             break mainLoop; \r
338             }\r
339                 \r
340             aByte = byteBuffer[bytePos++];\r
341             charBuffer[ucPos++] = (char)\r
342             (aByte << 8 | (byteBuffer[bytePos++] & 0xFF));\r
343             break;\r
344 \r
345             // switch to Unicode mode\r
346         case SCHANGEU:\r
347             fMode = UNICODEMODE;\r
348             break singleByteModeLoop;\r
349             //break;\r
350 \r
351             // handle all quote tags\r
352         case SQUOTE0: case SQUOTE1: case SQUOTE2: case SQUOTE3:\r
353         case SQUOTE4: case SQUOTE5: case SQUOTE6: case SQUOTE7:\r
354             // verify there is a byte following the tag\r
355             // if not, save state and break out\r
356             if(bytePos >= byteBufferLimit) {\r
357             --bytePos;\r
358             System.arraycopy(byteBuffer, bytePos,\r
359                      fBuffer, 0, \r
360                      byteBufferLimit - bytePos);\r
361             fBufferLength = byteBufferLimit - bytePos;\r
362             bytePos += fBufferLength;\r
363             break mainLoop; \r
364             }\r
365                 \r
366             // if the byte is in the range 0x00 - 0x7F, use\r
367             // static window n otherwise, use dynamic window n\r
368             int dByte = byteBuffer[bytePos++] & 0xFF;\r
369             charBuffer[ucPos++] = (char) \r
370             (dByte+ (dByte >= 0x00 && dByte < 0x80 \r
371                  ? sOffsets[aByte - SQUOTE0] \r
372                  : (fOffsets[aByte - SQUOTE0] \r
373                     - COMPRESSIONOFFSET))); \r
374             break;\r
375 \r
376             // handle all change tags\r
377         case SCHANGE0: case SCHANGE1: case SCHANGE2: case SCHANGE3:\r
378         case SCHANGE4: case SCHANGE5: case SCHANGE6: case SCHANGE7:\r
379             fCurrentWindow = aByte - SCHANGE0;\r
380             break;\r
381 \r
382             // handle all define tags\r
383         case SDEFINE0: case SDEFINE1: case SDEFINE2: case SDEFINE3:\r
384         case SDEFINE4: case SDEFINE5: case SDEFINE6: case SDEFINE7:\r
385             // verify there is a byte following the tag\r
386             // if not, save state and break out\r
387             if(bytePos >= byteBufferLimit) {\r
388             --bytePos;\r
389             System.arraycopy(byteBuffer, bytePos,\r
390                      fBuffer, 0, \r
391                      byteBufferLimit - bytePos);\r
392             fBufferLength = byteBufferLimit - bytePos;\r
393             bytePos += fBufferLength;\r
394             break mainLoop; \r
395             }\r
396 \r
397             fCurrentWindow = aByte - SDEFINE0;\r
398             fOffsets[fCurrentWindow] = \r
399             sOffsetTable[byteBuffer[bytePos++] & 0xFF];\r
400             break;\r
401 \r
402             // handle define extended tag\r
403         case SDEFINEX:\r
404             // verify we have two bytes following tag\r
405             // if not, save state and break out\r
406             if((bytePos + 1) >= byteBufferLimit ) {\r
407             --bytePos;\r
408             System.arraycopy(byteBuffer, bytePos,\r
409                      fBuffer, 0, \r
410                      byteBufferLimit - bytePos);\r
411             fBufferLength = byteBufferLimit - bytePos;\r
412             bytePos += fBufferLength;\r
413             break mainLoop; \r
414             }\r
415                 \r
416             aByte = byteBuffer[bytePos++] & 0xFF;\r
417             fCurrentWindow = (aByte & 0xE0) >> 5;\r
418             fOffsets[fCurrentWindow] = 0x10000 + \r
419             (0x80 * (((aByte & 0x1F) << 8) \r
420                  | (byteBuffer[bytePos++] & 0xFF)));\r
421             break;\r
422                             \r
423             // reserved, shouldn't happen\r
424         case SRESERVED:\r
425             break;\r
426 \r
427         } // end switch\r
428         } // end while\r
429         break;\r
430 \r
431         case UNICODEMODE:\r
432         // unicode mode decompression loop\r
433         unicodeModeLoop:\r
434         while(bytePos < byteBufferLimit && ucPos < charBufferLimit) {\r
435         aByte = byteBuffer[bytePos++] & 0xFF;\r
436         switch(aByte) {\r
437             // handle all define tags\r
438         case UDEFINE0: case UDEFINE1: case UDEFINE2: case UDEFINE3:\r
439         case UDEFINE4: case UDEFINE5: case UDEFINE6: case UDEFINE7:\r
440             // verify there is a byte following tag\r
441             // if not, save state and break out\r
442             if(bytePos >= byteBufferLimit ) {\r
443             --bytePos;\r
444             System.arraycopy(byteBuffer, bytePos,\r
445                      fBuffer, 0, \r
446                      byteBufferLimit - bytePos);\r
447             fBufferLength = byteBufferLimit - bytePos;\r
448             bytePos += fBufferLength;\r
449             break mainLoop; \r
450             }\r
451                 \r
452             fCurrentWindow = aByte - UDEFINE0;\r
453             fOffsets[fCurrentWindow] = \r
454             sOffsetTable[byteBuffer[bytePos++] & 0xFF];\r
455             fMode = SINGLEBYTEMODE;\r
456             break unicodeModeLoop;\r
457             //break;\r
458 \r
459             // handle define extended tag\r
460         case UDEFINEX:\r
461             // verify we have two bytes following tag\r
462             // if not, save state and break out\r
463             if((bytePos + 1) >= byteBufferLimit ) {\r
464             --bytePos;\r
465             System.arraycopy(byteBuffer, bytePos,\r
466                      fBuffer, 0, \r
467                      byteBufferLimit - bytePos);\r
468             fBufferLength = byteBufferLimit - bytePos;\r
469             bytePos += fBufferLength;\r
470             break mainLoop; \r
471             }\r
472             \r
473             aByte = byteBuffer[bytePos++] & 0xFF;\r
474             fCurrentWindow = (aByte & 0xE0) >> 5;\r
475             fOffsets[fCurrentWindow] = 0x10000 + \r
476             (0x80 * (((aByte & 0x1F) << 8) \r
477                  | (byteBuffer[bytePos++] & 0xFF)));\r
478             fMode = SINGLEBYTEMODE;\r
479             break unicodeModeLoop;\r
480             //break;\r
481 \r
482             // handle all change tags\r
483         case UCHANGE0: case UCHANGE1: case UCHANGE2: case UCHANGE3:\r
484         case UCHANGE4: case UCHANGE5: case UCHANGE6: case UCHANGE7:\r
485             fCurrentWindow = aByte - UCHANGE0;\r
486             fMode = SINGLEBYTEMODE;\r
487             break unicodeModeLoop;\r
488             //break;\r
489 \r
490             // quote unicode\r
491         case UQUOTEU:\r
492             // verify we have two bytes following tag\r
493             // if not, save state and break out\r
494             if(bytePos >= byteBufferLimit  - 1) {\r
495             --bytePos;\r
496             System.arraycopy(byteBuffer, bytePos,\r
497                      fBuffer, 0, \r
498                      byteBufferLimit - bytePos);\r
499             fBufferLength = byteBufferLimit - bytePos;\r
500             bytePos += fBufferLength;\r
501             break mainLoop; \r
502             }\r
503                 \r
504             aByte = byteBuffer[bytePos++];\r
505             charBuffer[ucPos++] = (char) \r
506             (aByte << 8 | (byteBuffer[bytePos++] & 0xFF));\r
507             break;\r
508 \r
509         default:\r
510             // verify there is a byte following tag\r
511             // if not, save state and break out\r
512             if(bytePos >= byteBufferLimit ) {\r
513             --bytePos;\r
514             System.arraycopy(byteBuffer, bytePos,\r
515                      fBuffer, 0, \r
516                      byteBufferLimit - bytePos);\r
517             fBufferLength = byteBufferLimit - bytePos;\r
518             bytePos += fBufferLength;\r
519             break mainLoop; \r
520             }\r
521 \r
522             charBuffer[ucPos++] = (char) \r
523             (aByte << 8 | (byteBuffer[bytePos++] & 0xFF));\r
524             break;\r
525 \r
526         } // end switch\r
527         } // end while\r
528         break;\r
529         \r
530         } // end switch( fMode )\r
531     } // end while\r
532 \r
533         // fill in output parameter\r
534     if(bytesRead != null)\r
535         bytesRead [0] = (bytePos - byteBufferStart);\r
536 \r
537         // return # of chars written\r
538     return (ucPos - charBufferStart);\r
539     }\r
540 \r
541     /** \r
542      * Reset the decompressor to its initial state. \r
543      * @stable ICU 2.4\r
544      */\r
545     public void reset()\r
546     {\r
547         // reset dynamic windows\r
548         fOffsets[0] = 0x0080;    // Latin-1\r
549         fOffsets[1] = 0x00C0;    // Latin-1 Supplement + Latin Extended-A\r
550         fOffsets[2] = 0x0400;    // Cyrillic\r
551         fOffsets[3] = 0x0600;    // Arabic\r
552         fOffsets[4] = 0x0900;    // Devanagari\r
553         fOffsets[5] = 0x3040;    // Hiragana\r
554         fOffsets[6] = 0x30A0;    // Katakana\r
555         fOffsets[7] = 0xFF00;    // Fullwidth ASCII\r
556 \r
557 \r
558         fCurrentWindow  = 0;                // Make current window Latin-1\r
559         fMode           = SINGLEBYTEMODE;   // Always start in single-byte mode\r
560     fBufferLength   = 0;                // Empty buffer\r
561     }\r
562 }\r