Home | History | Annotate | Download | only in util
      1 package org.bouncycastle.util;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.IOException;
      5 import java.io.OutputStream;
      6 import java.security.AccessController;
      7 import java.security.PrivilegedAction;
      8 import java.util.ArrayList;
      9 import java.util.Vector;
     10 
     11 /**
     12  * String utilities.
     13  */
     14 public final class Strings
     15 {
     16     private static String LINE_SEPARATOR;
     17 
     18     static
     19     {
     20        try
     21        {
     22            LINE_SEPARATOR = AccessController.doPrivileged(new PrivilegedAction<String>()
     23            {
     24                public String run()
     25                {
     26                    // the easy way
     27                    return System.getProperty("line.separator");
     28                }
     29            });
     30 
     31        }
     32        catch (Exception e)
     33        {
     34            try
     35            {
     36                // the harder way
     37                LINE_SEPARATOR = String.format("%n");
     38            }
     39            catch (Exception ef)
     40            {
     41                LINE_SEPARATOR = "\n";   // we're desperate use this...
     42            }
     43        }
     44     }
     45 
     46     public static String fromUTF8ByteArray(byte[] bytes)
     47     {
     48         int i = 0;
     49         int length = 0;
     50 
     51         while (i < bytes.length)
     52         {
     53             length++;
     54             if ((bytes[i] & 0xf0) == 0xf0)
     55             {
     56                 // surrogate pair
     57                 length++;
     58                 i += 4;
     59             }
     60             else if ((bytes[i] & 0xe0) == 0xe0)
     61             {
     62                 i += 3;
     63             }
     64             else if ((bytes[i] & 0xc0) == 0xc0)
     65             {
     66                 i += 2;
     67             }
     68             else
     69             {
     70                 i += 1;
     71             }
     72         }
     73 
     74         char[] cs = new char[length];
     75 
     76         i = 0;
     77         length = 0;
     78 
     79         while (i < bytes.length)
     80         {
     81             char ch;
     82 
     83             if ((bytes[i] & 0xf0) == 0xf0)
     84             {
     85                 int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i + 1] & 0x3F) << 12) | ((bytes[i + 2] & 0x3F) << 6) | (bytes[i + 3] & 0x3F);
     86                 int U = codePoint - 0x10000;
     87                 char W1 = (char)(0xD800 | (U >> 10));
     88                 char W2 = (char)(0xDC00 | (U & 0x3FF));
     89                 cs[length++] = W1;
     90                 ch = W2;
     91                 i += 4;
     92             }
     93             else if ((bytes[i] & 0xe0) == 0xe0)
     94             {
     95                 ch = (char)(((bytes[i] & 0x0f) << 12)
     96                     | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
     97                 i += 3;
     98             }
     99             else if ((bytes[i] & 0xd0) == 0xd0)
    100             {
    101                 ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
    102                 i += 2;
    103             }
    104             else if ((bytes[i] & 0xc0) == 0xc0)
    105             {
    106                 ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
    107                 i += 2;
    108             }
    109             else
    110             {
    111                 ch = (char)(bytes[i] & 0xff);
    112                 i += 1;
    113             }
    114 
    115             cs[length++] = ch;
    116         }
    117 
    118         return new String(cs);
    119     }
    120 
    121     public static byte[] toUTF8ByteArray(String string)
    122     {
    123         return toUTF8ByteArray(string.toCharArray());
    124     }
    125 
    126     public static byte[] toUTF8ByteArray(char[] string)
    127     {
    128         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    129 
    130         try
    131         {
    132             toUTF8ByteArray(string, bOut);
    133         }
    134         catch (IOException e)
    135         {
    136             throw new IllegalStateException("cannot encode string to byte array!");
    137         }
    138 
    139         return bOut.toByteArray();
    140     }
    141 
    142     public static void toUTF8ByteArray(char[] string, OutputStream sOut)
    143         throws IOException
    144     {
    145         char[] c = string;
    146         int i = 0;
    147 
    148         while (i < c.length)
    149         {
    150             char ch = c[i];
    151 
    152             if (ch < 0x0080)
    153             {
    154                 sOut.write(ch);
    155             }
    156             else if (ch < 0x0800)
    157             {
    158                 sOut.write(0xc0 | (ch >> 6));
    159                 sOut.write(0x80 | (ch & 0x3f));
    160             }
    161             // surrogate pair
    162             else if (ch >= 0xD800 && ch <= 0xDFFF)
    163             {
    164                 // in error - can only happen, if the Java String class has a
    165                 // bug.
    166                 if (i + 1 >= c.length)
    167                 {
    168                     throw new IllegalStateException("invalid UTF-16 codepoint");
    169                 }
    170                 char W1 = ch;
    171                 ch = c[++i];
    172                 char W2 = ch;
    173                 // in error - can only happen, if the Java String class has a
    174                 // bug.
    175                 if (W1 > 0xDBFF)
    176                 {
    177                     throw new IllegalStateException("invalid UTF-16 codepoint");
    178                 }
    179                 int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
    180                 sOut.write(0xf0 | (codePoint >> 18));
    181                 sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
    182                 sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
    183                 sOut.write(0x80 | (codePoint & 0x3F));
    184             }
    185             else
    186             {
    187                 sOut.write(0xe0 | (ch >> 12));
    188                 sOut.write(0x80 | ((ch >> 6) & 0x3F));
    189                 sOut.write(0x80 | (ch & 0x3F));
    190             }
    191 
    192             i++;
    193         }
    194     }
    195 
    196     /**
    197      * A locale independent version of toUpperCase.
    198      *
    199      * @param string input to be converted
    200      * @return a US Ascii uppercase version
    201      */
    202     public static String toUpperCase(String string)
    203     {
    204         boolean changed = false;
    205         char[] chars = string.toCharArray();
    206 
    207         for (int i = 0; i != chars.length; i++)
    208         {
    209             char ch = chars[i];
    210             if ('a' <= ch && 'z' >= ch)
    211             {
    212                 changed = true;
    213                 chars[i] = (char)(ch - 'a' + 'A');
    214             }
    215         }
    216 
    217         if (changed)
    218         {
    219             return new String(chars);
    220         }
    221 
    222         return string;
    223     }
    224 
    225     /**
    226      * A locale independent version of toLowerCase.
    227      *
    228      * @param string input to be converted
    229      * @return a US ASCII lowercase version
    230      */
    231     public static String toLowerCase(String string)
    232     {
    233         boolean changed = false;
    234         char[] chars = string.toCharArray();
    235 
    236         for (int i = 0; i != chars.length; i++)
    237         {
    238             char ch = chars[i];
    239             if ('A' <= ch && 'Z' >= ch)
    240             {
    241                 changed = true;
    242                 chars[i] = (char)(ch - 'A' + 'a');
    243             }
    244         }
    245 
    246         if (changed)
    247         {
    248             return new String(chars);
    249         }
    250 
    251         return string;
    252     }
    253 
    254     public static byte[] toByteArray(char[] chars)
    255     {
    256         byte[] bytes = new byte[chars.length];
    257 
    258         for (int i = 0; i != bytes.length; i++)
    259         {
    260             bytes[i] = (byte)chars[i];
    261         }
    262 
    263         return bytes;
    264     }
    265 
    266     public static byte[] toByteArray(String string)
    267     {
    268         byte[] bytes = new byte[string.length()];
    269 
    270         for (int i = 0; i != bytes.length; i++)
    271         {
    272             char ch = string.charAt(i);
    273 
    274             bytes[i] = (byte)ch;
    275         }
    276 
    277         return bytes;
    278     }
    279 
    280     public static int toByteArray(String s, byte[] buf, int off)
    281     {
    282         int count = s.length();
    283         for (int i = 0; i < count; ++i)
    284         {
    285             char c = s.charAt(i);
    286             buf[off + i] = (byte)c;
    287         }
    288         return count;
    289     }
    290 
    291     /**
    292      * Convert an array of 8 bit characters into a string.
    293      *
    294      * @param bytes 8 bit characters.
    295      * @return resulting String.
    296      */
    297     public static String fromByteArray(byte[] bytes)
    298     {
    299         return new String(asCharArray(bytes));
    300     }
    301 
    302     /**
    303      * Do a simple conversion of an array of 8 bit characters into a string.
    304      *
    305      * @param bytes 8 bit characters.
    306      * @return resulting String.
    307      */
    308     public static char[] asCharArray(byte[] bytes)
    309     {
    310         char[] chars = new char[bytes.length];
    311 
    312         for (int i = 0; i != chars.length; i++)
    313         {
    314             chars[i] = (char)(bytes[i] & 0xff);
    315         }
    316 
    317         return chars;
    318     }
    319 
    320     public static String[] split(String input, char delimiter)
    321     {
    322         Vector v = new Vector();
    323         boolean moreTokens = true;
    324         String subString;
    325 
    326         while (moreTokens)
    327         {
    328             int tokenLocation = input.indexOf(delimiter);
    329             if (tokenLocation > 0)
    330             {
    331                 subString = input.substring(0, tokenLocation);
    332                 v.addElement(subString);
    333                 input = input.substring(tokenLocation + 1);
    334             }
    335             else
    336             {
    337                 moreTokens = false;
    338                 v.addElement(input);
    339             }
    340         }
    341 
    342         String[] res = new String[v.size()];
    343 
    344         for (int i = 0; i != res.length; i++)
    345         {
    346             res[i] = (String)v.elementAt(i);
    347         }
    348         return res;
    349     }
    350 
    351     public static StringList newList()
    352     {
    353         return new StringListImpl();
    354     }
    355 
    356     public static String lineSeparator()
    357     {
    358         return LINE_SEPARATOR;
    359     }
    360 
    361     private static class StringListImpl
    362         extends ArrayList<String>
    363         implements StringList
    364     {
    365         public boolean add(String s)
    366         {
    367             return super.add(s);
    368         }
    369 
    370         public String set(int index, String element)
    371         {
    372             return super.set(index, element);
    373         }
    374 
    375         public void add(int index, String element)
    376         {
    377             super.add(index, element);
    378         }
    379 
    380         public String[] toStringArray()
    381         {
    382             String[] strs = new String[this.size()];
    383 
    384             for (int i = 0; i != strs.length; i++)
    385             {
    386                 strs[i] = this.get(i);
    387             }
    388 
    389             return strs;
    390         }
    391 
    392         public String[] toStringArray(int from, int to)
    393         {
    394             String[] strs = new String[to - from];
    395 
    396             for (int i = from; i != this.size() && i != to; i++)
    397             {
    398                 strs[i - from] = this.get(i);
    399             }
    400 
    401             return strs;
    402         }
    403     }
    404 }
    405