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 < decDivisors.length; i++)
    260             {
    261                 if (n < decDivisors[i])
    262                 {
    263                     if (started)
    264                         buffer.put((byte)'0');
    265                     continue;
    266                 }
    267
    268                 started= true;
    269                 long d= n / decDivisors[i];
    270                 buffer.put(DIGIT[(int)d]);
    271                 n= n - d * decDivisors[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
    290     public static void putCRLF(Buffer buffer)
    291     {
    292         buffer.put((byte)13);
    293         buffer.put((byte)10);
    294     }
    295
    296     public static boolean isPrefix(Buffer prefix,Buffer buffer)
    297     {
    298         if (prefix.length()>buffer.length())
    299             return false;
    300         int bi=buffer.getIndex();
    301         for (int i=prefix.getIndex(); i<prefix.putIndex();i++)
    302             if (prefix.peek(i)!=buffer.peek(bi++))
    303                 return false;
    304         return true;
    305     }
    306
    307     public static String to8859_1_String(Buffer buffer)
    308     {
    309         if (buffer.isImmutable())
    310             return buffer.toString();
    311
    312         try
    313         {
    314             byte[] bytes=buffer.array();
    315             if (bytes!=null)
    316                 return new String(bytes,buffer.getIndex(),buffer.length(),StringUtil.__ISO_8859_1);
    317
    318             StringBuffer b = new StringBuffer(buffer.length());
    319             for (int i=buffer.getIndex(),c=0;c<buffer.length();i++,c++)
    320                 b.append((char)(0x7f&buffer.peek(i)));
    321             return b.toString();
    322         }
    323         catch(UnsupportedEncodingException e)
    324         {
    325             e.printStackTrace();
    326             return buffer.toString();
    327         }
    328     }
    329 }