view src/org/eclipse/jetty/io/BufferUtil.java @ 1022:3718afd99988

HttpHeaders uses StringCache
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 01 Nov 2016 01:04:46 -0600
parents e350c11242be
children a8c92b0a08ed
line wrap: on
line source

//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.io;


/* ------------------------------------------------------------------------------- */
/** Buffer utility methods.
 * 
 * 
 */
public final class BufferUtil
{
	static final byte SPACE= 0x20;
	static final byte MINUS= '-';
	static final byte[] DIGIT=
	{(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'};

	/**
	 * Convert buffer to an integer.
	 * Parses up to the first non-numeric character. If no number is found an
	 * IllegalArgumentException is thrown
	 * @param buffer A buffer containing an integer. The position is not changed.
	 * @return an int 
	 */
	public static int toInt(Buffer buffer)
	{
		int val= 0;
		boolean started= false;
		boolean minus= false;
		for (int i= buffer.getIndex(); i < buffer.putIndex(); i++)
		{
			byte b= buffer.peek(i);
			if (b <= SPACE)
			{
				if (started)
					break;
			}
			else if (b >= '0' && b <= '9')
			{
				val= val * 10 + (b - '0');
				started= true;
			}
			else if (b == MINUS && !started)
			{
				minus= true;
			}
			else
				break;
		}

		if (started)
			return minus ? (-val) : val;
		throw new NumberFormatException(buffer.toString());
	}
	
	/**
	 * Convert string to an long.
	 * Parses up to the first non-numeric character. If no number is found an
	 * IllegalArgumentException is thrown
	 */
	public static long toLong(String s)
	{
		long val = 0;
		boolean started= false;
		boolean minus= false;
		for (int i = 0; i < s.length(); i++)
		{
			char c = s.charAt(i);
			if (c <= ' ')
			{
				if (started)
					break;
			}
			else if (c >= '0' && c <= '9')
			{
				val= val * 10L + (c - '0');
				started= true;
			}
			else if (c == '-' && !started)
			{
				minus= true;
			}
			else
				break;
		}

		if (started)
			return minus ? (-val) : val;
		throw new NumberFormatException(s);
	}

	public static void putHexInt(Buffer buffer, int n)
	{

		if (n < 0)
		{
			buffer.put((byte)'-');

			if (n == Integer.MIN_VALUE)
			{
				buffer.put((byte)(0x7f&'8'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				buffer.put((byte)(0x7f&'0'));
				
				return;
			}
			n= -n;
		}

		if (n < 0x10)
		{
			buffer.put(DIGIT[n]);
		}
		else
		{
			boolean started= false;
			// This assumes constant time int arithmatic
			for (int i= 0; i < hexDivisors.length; i++)
			{
				if (n < hexDivisors[i])
				{
					if (started)
						buffer.put((byte)'0');
					continue;
				}

				started= true;
				int d= n / hexDivisors[i];
				buffer.put(DIGIT[d]);
				n= n - d * hexDivisors[i];
			}
		}
	}

	/* ------------------------------------------------------------ */
	/**
	 * Add hex integer BEFORE current getIndex.
	 * @param buffer
	 * @param n
	 */
	public static void prependHexInt(Buffer buffer, int n)
	{
		if (n==0)
		{
			int gi=buffer.getIndex();
			buffer.poke(--gi,(byte)'0');
			buffer.setGetIndex(gi);
		}
		else
		{
			boolean minus=false;
			if (n<0)
			{
				minus=true;
				n=-n;
			}

			int gi=buffer.getIndex();
			while(n>0)
			{
				int d = 0xf&n;
				n=n>>4;
				buffer.poke(--gi,DIGIT[d]);
			}
			
			if (minus)
				buffer.poke(--gi,(byte)'-');
			buffer.setGetIndex(gi);
		}
	}
	

	public static void putDecLong(Buffer buffer, long n)
	{
		if (n < 0)
		{
			buffer.put((byte)'-');

			if (n == Long.MIN_VALUE)
			{
				buffer.put((byte)'9');
				n= 223372036854775808L;
			}
			else
				n= -n;
		}

		if (n < 10)
		{
			buffer.put(DIGIT[(int)n]);
		}
		else
		{
			boolean started= false;
			// This assumes constant time int arithmatic
			for (int i= 0; i < decDivisorsL.length; i++)
			{
				if (n < decDivisorsL[i])
				{
					if (started)
						buffer.put((byte)'0');
					continue;
				}

				started= true;
				long d= n / decDivisorsL[i];
				buffer.put(DIGIT[(int)d]);
				n= n - d * decDivisorsL[i];
			}
		}
	}
	
	private final static int[] hexDivisors=
	{
		0x10000000,
		0x1000000, 
		0x100000, 
		0x10000, 
		0x1000, 
		0x100, 
		0x10, 
		0x1 
	};

	private final static long[] decDivisorsL=
	{ 
		1000000000000000000L,
		100000000000000000L,
		10000000000000000L,
		1000000000000000L,
		100000000000000L,
		10000000000000L,
		1000000000000L,
		100000000000L,
		10000000000L,
		1000000000L,
		100000000L,
		10000000L,
		1000000L,
		100000L,
		10000L,
		1000L,
		100L,
		10L,
		1L 
	};


	public static void putCRLF(Buffer buffer)
	{
		buffer.put((byte)13);
		buffer.put((byte)10);
	}

}