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 }