/[classpath]/classpath/gnu/java/io/decode/DecoderUTF8.java
ViewVC logotype

Diff of /classpath/gnu/java/io/decode/DecoderUTF8.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5 by mark, Fri Apr 23 22:36:45 2004 UTC revision 1.5.2.1 by gnu_andrew, Sun Jan 16 02:14:45 2005 UTC
# Line 54  import java.io.IOException; Line 54  import java.io.IOException;
54    */    */
55  public class DecoderUTF8 extends Decoder  public class DecoderUTF8 extends Decoder
56  {  {
57    private static final char REPLACEMENT_CHARACTER = '\uFFFD';
58    
59    // If we're operating in stream mode and we encounter a surrogate pair that
60    // we can't fit in the output buffer, we use this field to store the
61    // second half of the surrogate pair.
62    private int pendingChar = -1;
63    
64  /*************************************************************************/  /*************************************************************************/
65    
# Line 77  DecoderUTF8(InputStream in) Line 83  DecoderUTF8(InputStream in)
83    * Counts the number of characters in a given byte array    * Counts the number of characters in a given byte array
84    */    */
85  public int  public int
86  charsInByteArray(byte[] buf, int offset, int len) throws CharConversionException  charsInByteArray(byte[] buf, int offset, int len)
87  {  {
88    int num_chars = 0;      int more = 0;
89        int val = 0;
90    // Scan the buffer with minimal validation checks      int num_chars = 0;
91    for (int i = offset; i < offset + len; i++)  
92      {      for (int i = offset; i < offset + len; i++)
93        // Three byte encoding case.        {
94        if ((buf[i] & 0xE0) == 0xE0) // 224          byte b = buf[i];
95          {  
96            i += 2;          if ((b & 0x80) == 0)
97            if (i >= buf.length)            {
98              throw new CharConversionException("Incomplete input");              if (more != 0)
99                    num_chars++; // ?
100            ++num_chars;              more = 0;
101          }              num_chars++;
102        // Two byte encoding case            }
103        else if ((buf[i] & 0xC0) == 0xC0) // 192          else if ((b & 0xC0) == 0x80)
104          {            {
105            ++i;              if (more == 0)
106            if (i >= buf.length)                  num_chars++; // ?
107              throw new CharConversionException("Incomplete input");              else
108                  {
109            ++num_chars;                  val <<= 6;
110          }                  val |= b & 0x3F;
111        // One byte encoding case                  more--;
112        else if (buf[i] < 0x80) // 128                  if (more == 0)
113          {                    {
114            ++num_chars;                      num_chars++;
115          }                      if (val >= 0x10000)
116        else                          num_chars++;
117          {                    }
118            throw new CharConversionException("Bad input encountered: " + buf[i]);                }
119          }            }
120      }          else
121              {
122                if (more != 0)
123                    num_chars++; // ?
124    
125                if ((b & 0xF8) == 0xF0)
126                  {
127                    val = b & 0x07;
128                    more = 3;
129                  }
130                else if ((b & 0xF0) == 0xE0)
131                  {
132                    val = b & 0x0F;
133                    more = 2;
134                  }
135                else if ((b & 0xE0) == 0xC0)
136                  {
137                    val = b & 0x1F;
138                    more = 1;
139                  }
140                else
141                    num_chars++; // ?
142              }
143          }
144    
145    return(num_chars);      return num_chars;
146  }  }
147    
148  /*************************************************************************/  /*************************************************************************/
# Line 123  charsInByteArray(byte[] buf, int offset, Line 152  charsInByteArray(byte[] buf, int offset,
152    */    */
153  public char[]  public char[]
154  convertToChars(byte[] buf, int buf_offset, int len, char cbuf[],  convertToChars(byte[] buf, int buf_offset, int len, char cbuf[],
155                 int cbuf_offset) throws CharConversionException                 int cbuf_offset)
156  {  {
157    int val;      int more = 0;
158        int val = 0;
159    
160    // Scan the buffer with full validation checks      for (int i = buf_offset; i < buf_offset + len; i++)
161    for (int i = buf_offset; i < buf_offset + len; i++)        {
162      {          byte b = buf[i];
163        // Three byte encoding case.  
164        if ((buf[i] & 0xE0) == 0xE0) // 224          if ((b & 0x80) == 0)
165          {            {
166            if ((i + 2) >= buf.length)              if (more != 0)
167              throw new CharConversionException("Incomplete input");                  cbuf[cbuf_offset++] = REPLACEMENT_CHARACTER;
168                more = 0;
169            val = (buf[i] & 0x0F) << 12;              cbuf[cbuf_offset++] = (char)b;
170            ++i;            }
171            else if ((b & 0xC0) == 0x80)
172            if ((buf[i] & 0x80) != 0x80)            {
173              throw new CharConversionException("Bad input byte: " + buf[i]);              if (more == 0)
174            val |= (buf[i] & 0x3F) << 6;                  cbuf[cbuf_offset++] = REPLACEMENT_CHARACTER;
175            ++i;              else
176                  {
177            if ((buf[i] & 0x80) != 0x80)                  val <<= 6;
178              throw new CharConversionException("Bad input byte: " + buf[i]);                  val |= b & 0x3F;
179            val |= (buf[i] & 0x3F);                  more--;
180          }                  if (more == 0)
181        // Two byte encoding case                    {
182        else if ((buf[i] & 0xC0) == 0xC0) // 192                      if (val < 0x10000)
183          {                          cbuf[cbuf_offset++] = (char)val;
184            if ((i + 1) >= buf.length)                      else
185              throw new CharConversionException("Incomplete input");                        {
186                            val -= 0x10000;
187            val = (buf[i] & 0x1F) << 6;                          cbuf[cbuf_offset++] = (char)(0xD800 + (val >> 10));
188            ++i;                          cbuf[cbuf_offset++] = (char)(0xDC00 + (val & 0x3FF));
189                          }
190            if ((buf[i] & 0x80) != 0x80)                    }
191              throw new CharConversionException("Bad input byte: " + buf[i]);                }
192            val |= (buf[i] & 0x3F);            }
193          }          else
194        // One byte encoding case            {
195        else if (buf[i] < 0x80) // 128              if (more != 0)
196          {                  cbuf[cbuf_offset++] = REPLACEMENT_CHARACTER;
197            val = buf[i];  
198          }              if ((b & 0xF8) == 0xF0)
199        else                {
200          {                  val = b & 0x07;
201            throw new CharConversionException("Bad input encountered: " + buf[i]);                  more = 3;
202          }                }
203                else if ((b & 0xF0) == 0xE0)
204        cbuf[cbuf_offset] = (char)val;                {
205        ++cbuf_offset;                  val = b & 0x0F;
206      }                  more = 2;
207                  }
208                else if ((b & 0xE0) == 0xC0)
209                  {
210                    val = b & 0x1F;
211                    more = 1;
212                  }
213                else
214                    cbuf[cbuf_offset++] = REPLACEMENT_CHARACTER;
215              }
216          }
217    
218    return(cbuf);      return cbuf;
219  }  }
220    
221  /*************************************************************************/  /*************************************************************************/
# Line 186  convertToChars(byte[] buf, int buf_offse Line 226  convertToChars(byte[] buf, int buf_offse
226  public int  public int
227  read(char[] cbuf, int offset, int len) throws IOException  read(char[] cbuf, int offset, int len) throws IOException
228  {  {
229    int val;      int start_offset = offset;
230        int more = 0;
231    // Note that this method of reading a single byte at a time is      int val = 0;
232    // inefficient and should probably be replaced  
233        if (pendingChar != -1 && len > 0)
234    for (int i = offset; i < offset + len; i++)        {
235      {          cbuf[offset++] = (char)pendingChar;
236        // Read a byte          pendingChar = -1;
237        int b = in.read();        }
238        if (b == -1)  
239          if (i == offset)      while (offset < start_offset + len)
240            return(-1);        {
241            int b = in.read();
242            if (b == -1)
243              {
244                if (more != 0)
245                    cbuf[offset++] = REPLACEMENT_CHARACTER;
246                if (offset - start_offset == 0)
247                    return -1;
248                return offset - start_offset;
249              }
250    
251            if ((b & 0x80) == 0)
252              {
253                if (more != 0)
254                    cbuf[offset++] = REPLACEMENT_CHARACTER;
255                more = 0;
256                cbuf[offset++] = (char)b;
257              }
258            else if ((b & 0xC0) == 0x80)
259              {
260                if (more == 0)
261                    cbuf[offset++] = REPLACEMENT_CHARACTER;
262                else
263                  {
264                    val <<= 6;
265                    val |= b & 0x3F;
266                    more--;
267                    if (more == 0)
268                      {
269                        if (val < 0x10000)
270                            cbuf[offset++] = (char)val;
271                        else
272                          {
273                            val -= 0x10000;
274                            cbuf[offset++] = (char)(0xD800 + (val >> 10));
275                            if (offset < start_offset + len)
276                                cbuf[offset++] = (char)(0xDC00 + (val & 0x3FF));
277                            else
278                                pendingChar = (char)(0xDC00 + (val & 0x3FF));
279                          }
280                      }
281                  }
282              }
283          else          else
284            return(i - offset);            {
285                if (more != 0)
286        // Three byte encoding case.                  cbuf[offset++] = REPLACEMENT_CHARACTER;
287        if ((b & 0xE0) == 0xE0) // 224  
288          {              if ((b & 0xF8) == 0xF0)
289            val = (b & 0x0F) << 12;                {
290                    val = b & 0x07;
291            if ((b = in.read()) == -1)                  more = 3;
292              throw new CharConversionException("Pre-mature end of input");                }
293                else if ((b & 0xF0) == 0xE0)
294            if ((b & 0x80) != 0x80)                {
295              throw new CharConversionException("Bad input byte: " + b);                  val = b & 0x0F;
296            val |= (b & 0x3F) << 6;                  more = 2;
297                  }
298            if ((b = in.read()) == -1)              else if ((b & 0xE0) == 0xC0)
299              throw new CharConversionException("Pre-mature end of input");                {
300                    val = b & 0x1F;
301            if ((b & 0x80) != 0x80)                  more = 1;
302              throw new CharConversionException("Bad input byte: " + b);                }
303            val |= (b & 0x3F);              else
304          }                  cbuf[offset++] = REPLACEMENT_CHARACTER;
305        // Two byte encoding case            }
306        else if ((b & 0xC0) == 0xC0) // 192          
307          {          // if no more bytes available, terminate loop early, instead of
308            val = (b & 0x1F) << 6;          // blocking in in.read().
309            // Do not test this in the for condition: it must call in.read() at
310            if ((b = in.read()) == -1)          // least once (and thus block if "in" is empty).
311              throw new CharConversionException("Pre-mature end of input");          if (more == 0 && in.available() <= 0)
312                break;
313            if ((b & 0x80) != 0x80)        }
             throw new CharConversionException("Bad input byte: " + b);  
           val |= (b & 0x3F);  
         }  
       // One byte encoding case  
       else if (b < 0x80) // 128  
         {  
           val = b;  
         }  
       else  
         {  
           throw new CharConversionException("Bad input encountered: " + b);  
         }  
   
       cbuf[i] = (char)val;  
   
       // if no more bytes available, terminate loop early, instead of  
       // blocking in in.read().  
       // Do not test this in the for condition: it must call in.read() at  
       // least once (and thus block if "in" is empty).  
       if (in.available() <= 0)  
         return (1 + i - offset);  
     }  
314    
315    return(len);      return offset - start_offset;
316  }  }
317    
318  } // class DecoderUTF8  } // class DecoderUTF8

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.5.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26