View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-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.io;
15  
16  import org.eclipse.jetty.io.BufferCache.CachedBuffer;
17  import org.eclipse.jetty.util.StringUtil;
18  
19  /* ------------------------------------------------------------------------------- */
20  /** Buffer utility methods.
21   * 
22   * 
23   */
24  public class BufferUtil
25  {
26      static final byte SPACE= 0x20;
27      static final byte MINUS= '-';
28      static final byte[] DIGIT=
29      {(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'};
30  
31      /**
32       * Convert buffer to an integer.
33       * Parses up to the first non-numeric character. If no number is found an
34       * IllegalArgumentException is thrown
35       * @param buffer A buffer containing an integer. The position is not changed.
36       * @return an int 
37       */
38      public static int toInt(Buffer buffer)
39      {
40          int val= 0;
41          boolean started= false;
42          boolean minus= false;
43          for (int i= buffer.getIndex(); i < buffer.putIndex(); i++)
44          {
45              byte b= buffer.peek(i);
46              if (b <= SPACE)
47              {
48                  if (started)
49                      break;
50              }
51              else if (b >= '0' && b <= '9')
52              {
53                  val= val * 10 + (b - '0');
54                  started= true;
55              }
56              else if (b == MINUS && !started)
57              {
58                  minus= true;
59              }
60              else
61                  break;
62          }
63  
64          if (started)
65              return minus ? (-val) : val;
66          throw new NumberFormatException(buffer.toString());
67      }
68      
69      /**
70       * Convert buffer to an long.
71       * Parses up to the first non-numeric character. If no number is found an
72       * IllegalArgumentException is thrown
73       * @param buffer A buffer containing an integer. The position is not changed.
74       * @return an int 
75       */
76      public static long toLong(Buffer buffer)
77      {
78          long val= 0;
79          boolean started= false;
80          boolean minus= false;
81          for (int i= buffer.getIndex(); i < buffer.putIndex(); i++)
82          {
83              byte b= buffer.peek(i);
84              if (b <= SPACE)
85              {
86                  if (started)
87                      break;
88              }
89              else if (b >= '0' && b <= '9')
90              {
91                  val= val * 10L + (b - '0');
92                  started= true;
93              }
94              else if (b == MINUS && !started)
95              {
96                  minus= true;
97              }
98              else
99                  break;
100         }
101 
102         if (started)
103             return minus ? (-val) : val;
104         throw new NumberFormatException(buffer.toString());
105     }
106 
107     public static void putHexInt(Buffer buffer, int n)
108     {
109 
110         if (n < 0)
111         {
112             buffer.put((byte)'-');
113 
114             if (n == Integer.MIN_VALUE)
115             {
116                 buffer.put((byte)(0x7f&'8'));
117                 buffer.put((byte)(0x7f&'0'));
118                 buffer.put((byte)(0x7f&'0'));
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                 
125                 return;
126             }
127             n= -n;
128         }
129 
130         if (n < 0x10)
131         {
132             buffer.put(DIGIT[n]);
133         }
134         else
135         {
136             boolean started= false;
137             // This assumes constant time int arithmatic
138             for (int i= 0; i < hexDivisors.length; i++)
139             {
140                 if (n < hexDivisors[i])
141                 {
142                     if (started)
143                         buffer.put((byte)'0');
144                     continue;
145                 }
146 
147                 started= true;
148                 int d= n / hexDivisors[i];
149                 buffer.put(DIGIT[d]);
150                 n= n - d * hexDivisors[i];
151             }
152         }
153     }
154 
155     /* ------------------------------------------------------------ */
156     /**
157      * Add hex integer BEFORE current getIndex.
158      * @param buffer
159      * @param n
160      */
161     public static void prependHexInt(Buffer buffer, int n)
162     {
163         if (n==0)
164         {
165             int gi=buffer.getIndex();
166             buffer.poke(--gi,(byte)'0');
167             buffer.setGetIndex(gi);
168         }
169         else
170         {
171             boolean minus=false;
172             if (n<0)
173             {
174                 minus=true;
175                 n=-n;
176             }
177 
178             int gi=buffer.getIndex();
179             while(n>0)
180             {
181                 int d = 0xf&n;
182                 n=n>>4;
183                 buffer.poke(--gi,DIGIT[d]);
184             }
185             
186             if (minus)
187                 buffer.poke(--gi,(byte)'-');
188             buffer.setGetIndex(gi);
189         }
190     }
191     
192 
193     /* ------------------------------------------------------------ */
194     public static void putDecInt(Buffer buffer, int n)
195     {
196         if (n < 0)
197         {
198             buffer.put((byte)'-');
199 
200             if (n == Integer.MIN_VALUE)
201             {
202                 buffer.put((byte)'2');
203                 n= 147483648;
204             }
205             else
206                 n= -n;
207         }
208 
209         if (n < 10)
210         {
211             buffer.put(DIGIT[n]);
212         }
213         else
214         {
215             boolean started= false;
216             // This assumes constant time int arithmatic
217             for (int i= 0; i < decDivisors.length; i++)
218             {
219                 if (n < decDivisors[i])
220                 {
221                     if (started)
222                         buffer.put((byte)'0');
223                     continue;
224                 }
225 
226                 started= true;
227                 int d= n / decDivisors[i];
228                 buffer.put(DIGIT[d]);
229                 n= n - d * decDivisors[i];
230             }
231         }
232     }
233     
234     public static void putDecLong(Buffer buffer, long n)
235     {
236         if (n < 0)
237         {
238             buffer.put((byte)'-');
239 
240             if (n == Long.MIN_VALUE)
241             {
242                 buffer.put((byte)'9');
243                 n= 223372036854775808L;
244             }
245             else
246                 n= -n;
247         }
248 
249         if (n < 10)
250         {
251             buffer.put(DIGIT[(int)n]);
252         }
253         else
254         {
255             boolean started= false;
256             // This assumes constant time int arithmatic
257             for (int i= 0; i < decDivisors.length; i++)
258             {
259                 if (n < decDivisors[i])
260                 {
261                     if (started)
262                         buffer.put((byte)'0');
263                     continue;
264                 }
265 
266                 started= true;
267                 long d= n / decDivisors[i];
268                 buffer.put(DIGIT[(int)d]);
269                 n= n - d * decDivisors[i];
270             }
271         }
272     }
273     
274     public static Buffer toBuffer(long value)
275     {
276         ByteArrayBuffer buf=new ByteArrayBuffer(16);
277         putDecLong(buf, value);
278         return buf;
279     }
280 
281     private final static int[] decDivisors=
282         { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
283 
284     private final static int[] hexDivisors=
285         { 0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 1 };
286 
287 
288     public static void putCRLF(Buffer buffer)
289     {
290         buffer.put((byte)13);
291         buffer.put((byte)10);
292     }
293     
294     public static boolean isPrefix(Buffer prefix,Buffer buffer)
295     {
296         if (prefix.length()>buffer.length())
297             return false;
298         int bi=buffer.getIndex();
299         for (int i=prefix.getIndex(); i<prefix.putIndex();i++)
300             if (prefix.peek(i)!=buffer.peek(bi++))
301                 return false;
302         return true;
303     }
304 
305     public static String to8859_1_String(Buffer buffer)
306     {
307         if (buffer instanceof CachedBuffer)
308             return buffer.toString();
309         return buffer.toString(StringUtil.__ISO_8859_1);
310     }
311 }