1package org.bouncycastle.util; 2 3import java.io.ByteArrayOutputStream; 4import java.io.IOException; 5import java.io.OutputStream; 6import java.util.Vector; 7 8public final class Strings 9{ 10 public static String fromUTF8ByteArray(byte[] bytes) 11 { 12 int i = 0; 13 int length = 0; 14 15 while (i < bytes.length) 16 { 17 length++; 18 if ((bytes[i] & 0xf0) == 0xf0) 19 { 20 // surrogate pair 21 length++; 22 i += 4; 23 } 24 else if ((bytes[i] & 0xe0) == 0xe0) 25 { 26 i += 3; 27 } 28 else if ((bytes[i] & 0xc0) == 0xc0) 29 { 30 i += 2; 31 } 32 else 33 { 34 i += 1; 35 } 36 } 37 38 char[] cs = new char[length]; 39 40 i = 0; 41 length = 0; 42 43 while (i < bytes.length) 44 { 45 char ch; 46 47 if ((bytes[i] & 0xf0) == 0xf0) 48 { 49 int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F); 50 int U = codePoint - 0x10000; 51 char W1 = (char)(0xD800 | (U >> 10)); 52 char W2 = (char)(0xDC00 | (U & 0x3FF)); 53 cs[length++] = W1; 54 ch = W2; 55 i += 4; 56 } 57 else if ((bytes[i] & 0xe0) == 0xe0) 58 { 59 ch = (char)(((bytes[i] & 0x0f) << 12) 60 | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); 61 i += 3; 62 } 63 else if ((bytes[i] & 0xd0) == 0xd0) 64 { 65 ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); 66 i += 2; 67 } 68 else if ((bytes[i] & 0xc0) == 0xc0) 69 { 70 ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); 71 i += 2; 72 } 73 else 74 { 75 ch = (char)(bytes[i] & 0xff); 76 i += 1; 77 } 78 79 cs[length++] = ch; 80 } 81 82 return new String(cs); 83 } 84 85 public static byte[] toUTF8ByteArray(String string) 86 { 87 return toUTF8ByteArray(string.toCharArray()); 88 } 89 90 public static byte[] toUTF8ByteArray(char[] string) 91 { 92 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 93 94 try 95 { 96 toUTF8ByteArray(string, bOut); 97 } 98 catch (IOException e) 99 { 100 throw new IllegalStateException("cannot encode string to byte array!"); 101 } 102 103 return bOut.toByteArray(); 104 } 105 106 public static void toUTF8ByteArray(char[] string, OutputStream sOut) 107 throws IOException 108 { 109 char[] c = string; 110 int i = 0; 111 112 while (i < c.length) 113 { 114 char ch = c[i]; 115 116 if (ch < 0x0080) 117 { 118 sOut.write(ch); 119 } 120 else if (ch < 0x0800) 121 { 122 sOut.write(0xc0 | (ch >> 6)); 123 sOut.write(0x80 | (ch & 0x3f)); 124 } 125 // surrogate pair 126 else if (ch >= 0xD800 && ch <= 0xDFFF) 127 { 128 // in error - can only happen, if the Java String class has a 129 // bug. 130 if (i + 1 >= c.length) 131 { 132 throw new IllegalStateException("invalid UTF-16 codepoint"); 133 } 134 char W1 = ch; 135 ch = c[++i]; 136 char W2 = ch; 137 // in error - can only happen, if the Java String class has a 138 // bug. 139 if (W1 > 0xDBFF) 140 { 141 throw new IllegalStateException("invalid UTF-16 codepoint"); 142 } 143 int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000; 144 sOut.write(0xf0 | (codePoint >> 18)); 145 sOut.write(0x80 | ((codePoint >> 12) & 0x3F)); 146 sOut.write(0x80 | ((codePoint >> 6) & 0x3F)); 147 sOut.write(0x80 | (codePoint & 0x3F)); 148 } 149 else 150 { 151 sOut.write(0xe0 | (ch >> 12)); 152 sOut.write(0x80 | ((ch >> 6) & 0x3F)); 153 sOut.write(0x80 | (ch & 0x3F)); 154 } 155 156 i++; 157 } 158 } 159 160 /** 161 * A locale independent version of toUpperCase. 162 * 163 * @param string input to be converted 164 * @return a US Ascii uppercase version 165 */ 166 public static String toUpperCase(String string) 167 { 168 boolean changed = false; 169 char[] chars = string.toCharArray(); 170 171 for (int i = 0; i != chars.length; i++) 172 { 173 char ch = chars[i]; 174 if ('a' <= ch && 'z' >= ch) 175 { 176 changed = true; 177 chars[i] = (char)(ch - 'a' + 'A'); 178 } 179 } 180 181 if (changed) 182 { 183 return new String(chars); 184 } 185 186 return string; 187 } 188 189 /** 190 * A locale independent version of toLowerCase. 191 * 192 * @param string input to be converted 193 * @return a US ASCII lowercase version 194 */ 195 public static String toLowerCase(String string) 196 { 197 boolean changed = false; 198 char[] chars = string.toCharArray(); 199 200 for (int i = 0; i != chars.length; i++) 201 { 202 char ch = chars[i]; 203 if ('A' <= ch && 'Z' >= ch) 204 { 205 changed = true; 206 chars[i] = (char)(ch - 'A' + 'a'); 207 } 208 } 209 210 if (changed) 211 { 212 return new String(chars); 213 } 214 215 return string; 216 } 217 218 public static byte[] toByteArray(char[] chars) 219 { 220 byte[] bytes = new byte[chars.length]; 221 222 for (int i = 0; i != bytes.length; i++) 223 { 224 bytes[i] = (byte)chars[i]; 225 } 226 227 return bytes; 228 } 229 230 public static byte[] toByteArray(String string) 231 { 232 byte[] bytes = new byte[string.length()]; 233 234 for (int i = 0; i != bytes.length; i++) 235 { 236 char ch = string.charAt(i); 237 238 bytes[i] = (byte)ch; 239 } 240 241 return bytes; 242 } 243 244 /** 245 * Convert an array of 8 bit characters into a string. 246 * 247 * @param bytes 8 bit characters. 248 * @return resulting String. 249 */ 250 public static String fromByteArray(byte[] bytes) 251 { 252 return new String(asCharArray(bytes)); 253 } 254 255 /** 256 * Do a simple conversion of an array of 8 bit characters into a string. 257 * 258 * @param bytes 8 bit characters. 259 * @return resulting String. 260 */ 261 public static char[] asCharArray(byte[] bytes) 262 { 263 char[] chars = new char[bytes.length]; 264 265 for (int i = 0; i != chars.length; i++) 266 { 267 chars[i] = (char)(bytes[i] & 0xff); 268 } 269 270 return chars; 271 } 272 273 public static String[] split(String input, char delimiter) 274 { 275 Vector v = new Vector(); 276 boolean moreTokens = true; 277 String subString; 278 279 while (moreTokens) 280 { 281 int tokenLocation = input.indexOf(delimiter); 282 if (tokenLocation > 0) 283 { 284 subString = input.substring(0, tokenLocation); 285 v.addElement(subString); 286 input = input.substring(tokenLocation + 1); 287 } 288 else 289 { 290 moreTokens = false; 291 v.addElement(input); 292 } 293 } 294 295 String[] res = new String[v.size()]; 296 297 for (int i = 0; i != res.length; i++) 298 { 299 res[i] = (String)v.elementAt(i); 300 } 301 return res; 302 } 303} 304