View Javadoc

1   // ========================================================================
2   // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at 
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  
15  package org.mortbay.io;
16  
17  import java.io.UnsupportedEncodingException;
18  
19  import org.mortbay.util.StringUtil;
20  
21  /* ------------------------------------------------------------------------------- */
22  /** Buffer utility methods.
23   * 
24   * @author gregw
25   */
26  public class BufferUtil
27  {
28      static final byte SPACE= 0x20;
29      static final byte MINUS= '-';
30      static final byte[] DIGIT=
31      {(byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7',(byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F'};
32  
33      /**
34       * Convert buffer to an integer.
35       * Parses up to the first non-numeric character. If no number is found an
36       * IllegalArgumentException is thrown
37       * @param buffer A buffer containing an integer. The position is not changed.
38       * @return an int 
39       */
40      public static int toInt(Buffer buffer)
41      {
42          int val= 0;
43          boolean started= false;
44          boolean minus= false;
45          for (int i= buffer.getIndex(); i < buffer.putIndex(); i++)
46          {
47              byte b= buffer.peek(i);
48              if (b <= SPACE)
49              {
50                  if (started)
51                      break;
52              }
53              else if (b >= '0' && b <= '9')
54              {
55                  val= val * 10 + (b - '0');
56                  started= true;
57              }
58              else if (b == MINUS && !started)
59              {
60                  minus= true;
61              }
62              else
63                  break;
64          }
65  
66          if (started)
67              return minus ? (-val) : val;
68          throw new NumberFormatException(buffer.toString());
69      }
70      
71      /**
72       * Convert buffer to an long.
73       * Parses up to the first non-numeric character. If no number is found an
74       * IllegalArgumentException is thrown
75       * @param buffer A buffer containing an integer. The position is not changed.
76       * @return an int 
77       */
78      public static long toLong(Buffer buffer)
79      {
80          long val= 0;
81          boolean started= false;
82          boolean minus= false;
83          for (int i= buffer.getIndex(); i < buffer.putIndex(); i++)
84          {
85              byte b= buffer.peek(i);
86              if (b <= SPACE)
87              {
88                  if (started)
89                      break;
90              }
91              else if (b >= '0' && b <= '9')
92              {
93                  val= val * 10L + (b - '0');
94                  started= true;
95              }
96              else if (b == MINUS && !started)
97              {
98                  minus= true;
99              }
100             else
101                 break;
102         }
103 
104         if (started)
105             return minus ? (-val) : val;
106         throw new NumberFormatException(buffer.toString());
107     }
108 
109     public static void putHexInt(Buffer buffer, int n)
110     {
111 
112         if (n < 0)
113         {
114             buffer.put((byte)'-');
115 
116             if (n == Integer.MIN_VALUE)
117             {
118                 buffer.put((byte)(0x7f&'8'));
119                 buffer.put((byte)(0x7f&'0'));
120                 buffer.put((byte)(0x7f&'0'));
121                 buffer.put((byte)(0x7f&'0'));
122                 buffer.put((byte)(0x7f&'0'));
123                 buffer.put((byte)(0x7f&'0'));
124                 buffer.put((byte)(0x7f&'0'));
125                 buffer.put((byte)(0x7f&'0'));
126                 
127                 return;
128             }
129             n= -n;
130         }
131 
132         if (n < 0x10)
133         {
134             buffer.put(DIGIT[n]);
135         }
136         else
137         {
138             boolean started= false;
139             // This assumes constant time int arithmatic
140             for (int i= 0; i < hexDivisors.length; i++)
141             {
142                 if (n < hexDivisors[i])
143                 {
144                     if (started)
145                         buffer.put((byte)'0');
146                     continue;
147                 }
148 
149                 started= true;
150                 int d= n / hexDivisors[i];
151                 buffer.put(DIGIT[d]);
152                 n= n - d * hexDivisors[i];
153             }
154         }
155     }
156 
157     /* ------------------------------------------------------------ */
158     /**
159      * Add hex integer BEFORE current getIndex.
160      * @param buffer
161      * @param n
162      */
163     public static void prependHexInt(Buffer buffer, int n)
164     {
165         if (n==0)
166         {
167             int gi=buffer.getIndex();
168             buffer.poke(--gi,(byte)'0');
169             buffer.setGetIndex(gi);
170         }
171         else
172         {
173             boolean minus=false;
174             if (n<0)
175             {
176                 minus=true;
177                 n=-n;
178             }
179 
180             int gi=buffer.getIndex();
181             while(n>0)
182             {
183                 int d = 0xf&n;
184                 n=n>>4;
185                 buffer.poke(--gi,DIGIT[d]);
186             }
187             
188             if (minus)
189                 buffer.poke(--gi,(byte)'-');
190             buffer.setGetIndex(gi);
191         }
192     }
193     
194 
195     /* ------------------------------------------------------------ */
196     public static void putDecInt(Buffer buffer, int n)
197     {
198         if (n < 0)
199         {
200             buffer.put((byte)'-');
201 
202             if (n == Integer.MIN_VALUE)
203             {
204                 buffer.put((byte)'2');
205                 n= 147483648;
206             }
207             else
208                 n= -n;
209         }
210 
211         if (n < 10)
212         {
213             buffer.put(DIGIT[n]);
214         }
215         else
216         {
217             boolean started= false;
218             // This assumes constant time int arithmatic
219             for (int i= 0; i < decDivisors.length; i++)
220             {
221                 if (n < decDivisors[i])
222                 {
223                     if (started)
224                         buffer.put((byte)'0');
225                     continue;
226                 }
227 
228                 started= true;
229                 int d= n / decDivisors[i];
230                 buffer.put(DIGIT[d]);
231                 n= n - d * decDivisors[i];
232             }
233         }
234     }
235     
236     public static void putDecLong(Buffer buffer, long n)
237     {
238         if (n < 0)
239         {
240             buffer.put((byte)'-');
241 
242             if (n == Long.MIN_VALUE)
243             {
244                 buffer.put((byte)'9');
245                 n= 223372036854775808L;
246             }
247             else
248                 n= -n;
249         }
250 
251         if (n < 10)
252         {
253             buffer.put(DIGIT[(int)n]);
254         }
255         else
256         {
257             boolean started= false;
258             // This assumes constant time int arithmatic
259             for (int i= 0; i < decDivisors.length; i++)
260             {
261                 if (n < decDivisors[i])
262                 {
263                     if (started)
264                         buffer.put((byte)'0');
265                     continue;
266                 }
267 
268                 started= true;
269                 long d= n / decDivisors[i];
270                 buffer.put(DIGIT[(int)d]);
271                 n= n - d * decDivisors[i];
272             }
273         }
274     }
275     
276     public static Buffer toBuffer(long value)
277     {
278         ByteArrayBuffer buf=new ByteArrayBuffer(16);
279         putDecLong(buf, value);
280         return buf;
281     }
282 
283     private static int[] decDivisors=
284         { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
285 
286     private static int[] hexDivisors=
287         { 0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 1 };
288 
289 
290     public static void putCRLF(Buffer buffer)
291     {
292         buffer.put((byte)13);
293         buffer.put((byte)10);
294     }
295     
296     public static boolean isPrefix(Buffer prefix,Buffer buffer)
297     {
298         if (prefix.length()>buffer.length())
299             return false;
300         int bi=buffer.getIndex();
301         for (int i=prefix.getIndex(); i<prefix.putIndex();i++)
302             if (prefix.peek(i)!=buffer.peek(bi++))
303                 return false;
304         return true;
305     }
306 
307     public static String to8859_1_String(Buffer buffer)
308     {
309         if (buffer.isImmutable())
310             return buffer.toString();
311         
312         try
313         {
314             byte[] bytes=buffer.array();
315             if (bytes!=null)
316                 return new String(bytes,buffer.getIndex(),buffer.length(),StringUtil.__ISO_8859_1);
317             
318             StringBuffer b = new StringBuffer(buffer.length());
319             for (int i=buffer.getIndex(),c=0;c<buffer.length();i++,c++)
320                 b.append((char)(0x7f&buffer.peek(i)));
321             return b.toString();
322         }
323         catch(UnsupportedEncodingException e)
324         {
325             e.printStackTrace();
326             return buffer.toString();
327         }
328     }
329 }