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