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 < decDivisorsL.length; i++)
260             {
261                 if (n < decDivisorsL[i])
262                 {
263                     if (started)
264                         buffer.put((byte)'0');
265                     continue;
266                 }
267 
268                 started= true;
269                 long d= n / decDivisorsL[i];
270                 buffer.put(DIGIT[(int)d]);
271                 n= n - d * decDivisorsL[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     private final static long[] decDivisorsL=
290     { 
291         1000000000000000000L,
292         100000000000000000L,
293         10000000000000000L,
294         1000000000000000L,
295         100000000000000L,
296         10000000000000L,
297         1000000000000L,
298         100000000000L,
299         10000000000L,
300         1000000000L,
301         100000000L,
302         10000000L,
303         1000000L,
304         100000L,
305         10000L,
306         1000L,
307         100L,
308         10L,
309         1L 
310     };
311 
312     public static void putCRLF(Buffer buffer)
313     {
314         buffer.put((byte)13);
315         buffer.put((byte)10);
316     }
317     
318     public static boolean isPrefix(Buffer prefix,Buffer buffer)
319     {
320         if (prefix.length()>buffer.length())
321             return false;
322         int bi=buffer.getIndex();
323         for (int i=prefix.getIndex(); i<prefix.putIndex();i++)
324             if (prefix.peek(i)!=buffer.peek(bi++))
325                 return false;
326         return true;
327     }
328 
329     public static String to8859_1_String(Buffer buffer)
330     {
331         if (buffer.isImmutable())
332             return buffer.toString();
333         
334         try
335         {
336             byte[] bytes=buffer.array();
337             if (bytes!=null)
338                 return new String(bytes,buffer.getIndex(),buffer.length(),StringUtil.__ISO_8859_1);
339             
340             StringBuffer b = new StringBuffer(buffer.length());
341             for (int i=buffer.getIndex(),c=0;c<buffer.length();i++,c++)
342                 b.append((char)(0x7f&buffer.peek(i)));
343             return b.toString();
344         }
345         catch(UnsupportedEncodingException e)
346         {
347             e.printStackTrace();
348             return buffer.toString();
349         }
350     }
351 }