1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.io; 20 21 import org.eclipse.jetty.io.BufferCache.CachedBuffer; 22 import org.eclipse.jetty.util.StringUtil; 23 24 /* ------------------------------------------------------------------------------- */ 25 /** Buffer utility methods. 26 * 27 * 28 */ 29 public class BufferUtil 30 { 31 static final byte SPACE= 0x20; 32 static final byte MINUS= '-'; 33 static final byte[] DIGIT= 34 {(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'}; 35 36 /** 37 * Convert buffer to an integer. 38 * Parses up to the first non-numeric character. If no number is found an 39 * IllegalArgumentException is thrown 40 * @param buffer A buffer containing an integer. The position is not changed. 41 * @return an int 42 */ toInt(Buffer buffer)43 public static int toInt(Buffer buffer) 44 { 45 int val= 0; 46 boolean started= false; 47 boolean minus= false; 48 for (int i= buffer.getIndex(); i < buffer.putIndex(); i++) 49 { 50 byte b= buffer.peek(i); 51 if (b <= SPACE) 52 { 53 if (started) 54 break; 55 } 56 else if (b >= '0' && b <= '9') 57 { 58 val= val * 10 + (b - '0'); 59 started= true; 60 } 61 else if (b == MINUS && !started) 62 { 63 minus= true; 64 } 65 else 66 break; 67 } 68 69 if (started) 70 return minus ? (-val) : val; 71 throw new NumberFormatException(buffer.toString()); 72 } 73 74 /** 75 * Convert buffer to an long. 76 * Parses up to the first non-numeric character. If no number is found an 77 * IllegalArgumentException is thrown 78 * @param buffer A buffer containing an integer. The position is not changed. 79 * @return an int 80 */ toLong(Buffer buffer)81 public static long toLong(Buffer buffer) 82 { 83 long val= 0; 84 boolean started= false; 85 boolean minus= false; 86 for (int i= buffer.getIndex(); i < buffer.putIndex(); i++) 87 { 88 byte b= buffer.peek(i); 89 if (b <= SPACE) 90 { 91 if (started) 92 break; 93 } 94 else if (b >= '0' && b <= '9') 95 { 96 val= val * 10L + (b - '0'); 97 started= true; 98 } 99 else if (b == MINUS && !started) 100 { 101 minus= true; 102 } 103 else 104 break; 105 } 106 107 if (started) 108 return minus ? (-val) : val; 109 throw new NumberFormatException(buffer.toString()); 110 } 111 putHexInt(Buffer buffer, int n)112 public static void putHexInt(Buffer buffer, int n) 113 { 114 115 if (n < 0) 116 { 117 buffer.put((byte)'-'); 118 119 if (n == Integer.MIN_VALUE) 120 { 121 buffer.put((byte)(0x7f&'8')); 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 buffer.put((byte)(0x7f&'0')); 127 buffer.put((byte)(0x7f&'0')); 128 buffer.put((byte)(0x7f&'0')); 129 130 return; 131 } 132 n= -n; 133 } 134 135 if (n < 0x10) 136 { 137 buffer.put(DIGIT[n]); 138 } 139 else 140 { 141 boolean started= false; 142 // This assumes constant time int arithmatic 143 for (int i= 0; i < hexDivisors.length; i++) 144 { 145 if (n < hexDivisors[i]) 146 { 147 if (started) 148 buffer.put((byte)'0'); 149 continue; 150 } 151 152 started= true; 153 int d= n / hexDivisors[i]; 154 buffer.put(DIGIT[d]); 155 n= n - d * hexDivisors[i]; 156 } 157 } 158 } 159 160 /* ------------------------------------------------------------ */ 161 /** 162 * Add hex integer BEFORE current getIndex. 163 * @param buffer 164 * @param n 165 */ prependHexInt(Buffer buffer, int n)166 public static void prependHexInt(Buffer buffer, int n) 167 { 168 if (n==0) 169 { 170 int gi=buffer.getIndex(); 171 buffer.poke(--gi,(byte)'0'); 172 buffer.setGetIndex(gi); 173 } 174 else 175 { 176 boolean minus=false; 177 if (n<0) 178 { 179 minus=true; 180 n=-n; 181 } 182 183 int gi=buffer.getIndex(); 184 while(n>0) 185 { 186 int d = 0xf&n; 187 n=n>>4; 188 buffer.poke(--gi,DIGIT[d]); 189 } 190 191 if (minus) 192 buffer.poke(--gi,(byte)'-'); 193 buffer.setGetIndex(gi); 194 } 195 } 196 197 198 /* ------------------------------------------------------------ */ putDecInt(Buffer buffer, int n)199 public static void putDecInt(Buffer buffer, int n) 200 { 201 if (n < 0) 202 { 203 buffer.put((byte)'-'); 204 205 if (n == Integer.MIN_VALUE) 206 { 207 buffer.put((byte)'2'); 208 n= 147483648; 209 } 210 else 211 n= -n; 212 } 213 214 if (n < 10) 215 { 216 buffer.put(DIGIT[n]); 217 } 218 else 219 { 220 boolean started= false; 221 // This assumes constant time int arithmatic 222 for (int i= 0; i < decDivisors.length; i++) 223 { 224 if (n < decDivisors[i]) 225 { 226 if (started) 227 buffer.put((byte)'0'); 228 continue; 229 } 230 231 started= true; 232 int d= n / decDivisors[i]; 233 buffer.put(DIGIT[d]); 234 n= n - d * decDivisors[i]; 235 } 236 } 237 } 238 putDecLong(Buffer buffer, long n)239 public static void putDecLong(Buffer buffer, long n) 240 { 241 if (n < 0) 242 { 243 buffer.put((byte)'-'); 244 245 if (n == Long.MIN_VALUE) 246 { 247 buffer.put((byte)'9'); 248 n= 223372036854775808L; 249 } 250 else 251 n= -n; 252 } 253 254 if (n < 10) 255 { 256 buffer.put(DIGIT[(int)n]); 257 } 258 else 259 { 260 boolean started= false; 261 // This assumes constant time int arithmatic 262 for (int i= 0; i < decDivisorsL.length; i++) 263 { 264 if (n < decDivisorsL[i]) 265 { 266 if (started) 267 buffer.put((byte)'0'); 268 continue; 269 } 270 271 started= true; 272 long d= n / decDivisorsL[i]; 273 buffer.put(DIGIT[(int)d]); 274 n= n - d * decDivisorsL[i]; 275 } 276 } 277 } 278 toBuffer(long value)279 public static Buffer toBuffer(long value) 280 { 281 ByteArrayBuffer buf=new ByteArrayBuffer(32); 282 putDecLong(buf, value); 283 return buf; 284 } 285 286 private final static int[] decDivisors= 287 { 288 1000000000, 289 100000000, 290 10000000, 291 1000000, 292 100000, 293 10000, 294 1000, 295 100, 296 10, 297 1 298 }; 299 300 private final static int[] hexDivisors= 301 { 302 0x10000000, 303 0x1000000, 304 0x100000, 305 0x10000, 306 0x1000, 307 0x100, 308 0x10, 309 0x1 310 }; 311 312 private final static long[] decDivisorsL= 313 { 314 1000000000000000000L, 315 100000000000000000L, 316 10000000000000000L, 317 1000000000000000L, 318 100000000000000L, 319 10000000000000L, 320 1000000000000L, 321 100000000000L, 322 10000000000L, 323 1000000000L, 324 100000000L, 325 10000000L, 326 1000000L, 327 100000L, 328 10000L, 329 1000L, 330 100L, 331 10L, 332 1L 333 }; 334 335 putCRLF(Buffer buffer)336 public static void putCRLF(Buffer buffer) 337 { 338 buffer.put((byte)13); 339 buffer.put((byte)10); 340 } 341 isPrefix(Buffer prefix,Buffer buffer)342 public static boolean isPrefix(Buffer prefix,Buffer buffer) 343 { 344 if (prefix.length()>buffer.length()) 345 return false; 346 int bi=buffer.getIndex(); 347 for (int i=prefix.getIndex(); i<prefix.putIndex();i++) 348 if (prefix.peek(i)!=buffer.peek(bi++)) 349 return false; 350 return true; 351 } 352 to8859_1_String(Buffer buffer)353 public static String to8859_1_String(Buffer buffer) 354 { 355 if (buffer instanceof CachedBuffer) 356 return buffer.toString(); 357 return buffer.toString(StringUtil.__ISO_8859_1_CHARSET); 358 } 359 } 360