View Javadoc

1   // ========================================================================
2   // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.util;
15  
16  /* ------------------------------------------------------------ */
17  /** UTF-8 StringBuffer.
18   *
19   * This class wraps a standard {@link java.lang.StringBuffer} and provides methods to append 
20   * UTF-8 encoded bytes, that are converted into characters.
21   * 
22   * This class is stateful and up to 6  calls to {@link #append(byte)} may be needed before 
23   * state a character is appended to the string buffer.
24   * 
25   * The UTF-8 decoding is done by this class and no additional buffers or Readers are used.
26   * The UTF-8 code was inspired by http://javolution.org
27   * 
28   * This class is not synchronised and should probably be called Utf8StringBuilder
29   */
30  public class Utf8StringBuffer 
31  {
32      StringBuffer _buffer;
33      int _more;
34      int _bits;
35      
36      public Utf8StringBuffer()
37      {
38          _buffer=new StringBuffer();
39      }
40      
41      public Utf8StringBuffer(int capacity)
42      {
43          _buffer=new StringBuffer(capacity);
44      }
45  
46      public void append(byte[] b,int offset, int length)
47      {
48          int end=offset+length;
49          for (int i=offset; i<end;i++)
50              append(b[i]);
51      }
52      
53      public void append(byte b)
54      {
55          if (b>=0)
56          {
57              if (_more>0)
58              {
59                  _buffer.append('?');
60                  _more=0;
61                  _bits=0;
62              }
63              else
64                  _buffer.append((char)(0x7f&b));
65          }
66          else if (_more==0)
67          {
68              if ((b&0xc0)!=0xc0)
69              {
70                  // 10xxxxxx
71                  _buffer.append('?');
72                  _more=0;
73                  _bits=0;
74              }
75              else
76  
77              { 
78                  if ((b & 0xe0) == 0xc0)
79                  {
80                      //110xxxxx
81                      _more=1;
82                      _bits=b&0x1f;
83                  }
84                  else if ((b & 0xf0) == 0xe0)
85                  {
86                      //1110xxxx
87                      _more=2;
88                      _bits=b&0x0f;
89                  }
90                  else if ((b & 0xf8) == 0xf0)
91                  {
92                      //11110xxx
93                      _more=3;
94                      _bits=b&0x07;
95                  }
96                  else if ((b & 0xfc) == 0xf8)
97                  {
98                      //111110xx
99                      _more=4;
100                     _bits=b&0x03;
101                 }
102                 else if ((b & 0xfe) == 0xfc) 
103                 {
104                     //1111110x
105                     _more=5;
106                     _bits=b&0x01;
107                 }
108                 else
109                 {
110                     throw new IllegalArgumentException("!utf8");
111                 }
112                 
113             }
114         }
115         else
116         {
117             if ((b&0xc0)==0xc0)
118             {    // 11??????
119                 _buffer.append('?');
120                 _more=0;
121                 _bits=0;
122                 throw new IllegalArgumentException("!utf8");
123             }
124             else
125             {
126                 // 10xxxxxx
127                 _bits=(_bits<<6)|(b&0x3f);
128                 if (--_more==0)
129                     _buffer.append(Character.toChars(_bits));
130             }
131         }
132     }
133     
134     public int length()
135     {
136         return _buffer.length();
137     }
138     
139     public void reset()
140     {
141         _buffer.setLength(0);
142         _more=0;
143         _bits=0;
144     }
145     
146     public StringBuffer getStringBuffer()
147     {
148         if (_more!=0)
149             throw new IllegalStateException("!utf8");
150         return _buffer;
151     }
152     
153     @Override
154     public String toString()
155     {
156         if (_more!=0)
157             throw new IllegalStateException("!utf8");
158         return _buffer.toString();
159     }
160 }