1 28 29 package com.caucho.es; 30 31 import com.caucho.util.CharBuffer; 32 import com.caucho.util.IntMap; 33 34 import java.text.CharacterIterator ; 35 36 39 public class ESString extends ESBase { 40 static ESId NULL; 41 static ESId LENGTH; 42 private static ESId ints[]; 43 44 protected String string; 45 protected int hashCode; 46 47 50 protected ESString(String string) 51 { 52 if (ints == null) { 53 ints = new ESId[128]; 54 NULL = ESId.intern(""); 55 LENGTH = ESId.intern("length"); 56 57 for (int i = 0; i < ints.length; i++) 58 ints[i] = ESId.intern(String.valueOf(i)); 59 } 60 61 prototype = esNull; 62 this.string = string; 63 } 64 65 public static ESString create(String string) 66 { 67 return string == null ? NULL : new ESString(string); 68 } 69 70 public static ESBase toStr(String string) 71 { 72 return string == null ? esNull : new ESString(string); 73 } 74 75 public static ESString create(int i) 76 { 77 if (i >= 0 && i < ints.length) 78 return ints[i]; 79 80 return new ESString(String.valueOf(i)); 81 } 82 83 public static ESString createFromCharCode(char c) 84 { 85 return new ESString(String.valueOf((char) c)); 86 } 87 88 public static ESString create(CharBuffer cb) 89 { 90 return new ESString(cb.toString()); 91 } 92 93 96 public static ESString create(Object obj) 97 { 98 return new ESString(String.valueOf(obj)); 99 } 100 101 public ESBase typeof() throws ESException 102 { 103 return ESString.create("string"); 104 } 105 106 public Class getJavaType() 107 { 108 return String .class; 109 } 110 111 public double toNum() 112 { 113 return parseFloat(this, true); 114 } 115 116 public ESString toStr() 117 { 118 return this; 119 } 120 121 public boolean isString() 122 { 123 return true; 124 } 125 126 public ESString toSource(IntMap map, boolean isLoopPass) 127 { 128 if (isLoopPass) 129 return null; 130 131 return ESString.create("\"" + string + "\""); 132 } 133 134 public ESObject toObject() 135 { 136 ESObject obj = new ESWrapper("String", Global.getGlobalProto().stringProto, this); 137 138 obj.put(LENGTH, ESNumber.create(this.string.length()), 139 DONT_ENUM|DONT_DELETE|READ_ONLY); 140 141 return obj; 142 } 143 144 public Object toJavaObject() 145 { 146 return string; 147 } 148 149 public ESBase getProperty(ESString key) throws Throwable 150 { 151 if (key.equals(LENGTH)) 152 return ESNumber.create(this.string.length()); 153 else 154 return Global.getGlobalProto().stringProto.getProperty(key); 155 } 156 157 public boolean ecmaEquals(ESBase b) throws Throwable 158 { 159 if (b == esNull) 160 return false; 161 else if (b instanceof ESString) 162 return string.equals(((ESString) b).string); 163 else if (b instanceof ESObject) { 164 ESBase pb = b.toPrimitive(NONE); 165 if (pb instanceof ESString) 166 return equals(pb); 167 else 168 return toNum() == pb.toNum(); 169 } else { 170 return toNum() == b.toNum(); 171 } 172 } 173 174 public ESBase plus(ESBase b) throws Throwable 175 { 176 ESBase prim = b.toPrimitive(NONE); 177 178 return ESString.create(string + prim.toStr().toString()); 179 } 180 181 char charAt(int i) { return string.charAt(i); } 182 183 public char carefulCharAt(int i) 184 { 185 if (i >= string.length()) 186 return CharacterIterator.DONE; 187 else 188 return string.charAt(i); 189 } 190 191 int length() { return string.length(); } 192 193 boolean regionMatches(int i, String test, int j, int len) 194 { 195 return string.regionMatches(i, test, j, len); 196 } 197 198 public int hashCode() 199 { 200 int hash = hashCode; 201 202 if (hash != 0) 203 return hash; 204 205 hash = 1021; 206 int len = string.length(); 207 208 for (int i = 0; i < len; i++) 209 hash = 65521 * hash + (string.charAt(i) + 1) * 251; 210 211 hashCode = hash; 212 213 return hash; 214 } 215 216 public boolean equals(Object a) 217 { 218 if (this == a) 219 return true; 220 else if (a instanceof ESString) 221 return string.equals(((ESString) a).string); 222 else 223 return false; 224 } 225 226 int compareTo(ESString b) 227 { 228 return string.compareTo(b.string); 229 } 230 231 int indexOf(ESString a, int pos) { return string.indexOf(a.string, pos); } 232 int lastIndexOf(ESString a, int pos) 233 { 234 return string.lastIndexOf(a.string, pos); 235 } 236 237 ESString substring(int begin, int end) 238 { 239 return ESString.create(string.substring(begin, end)); 240 } 241 242 ESString substring(int begin) 243 { 244 return substring(begin, string.length()); 245 } 246 247 ESString toLowerCase() 248 { 249 return ESString.create(string.toLowerCase()); 250 } 251 252 ESString toUpperCase() 253 { 254 return ESString.create(string.toUpperCase()); 255 } 256 257 ESBoolean contains(ESBase b) throws Throwable 258 { 259 ESString sb = b.toStr(); 260 if (sb.string.length() == 0) 261 return ESBoolean.TRUE; 262 263 int len = string.length(); 264 for (int i = 0; i <= len; i++) { 265 if (string.regionMatches(i, sb.string, 0, sb.length())) 266 return ESBoolean.TRUE; 267 } 268 269 return ESBoolean.FALSE; 270 } 271 272 ESBoolean startsWith(ESBase b) throws Throwable 273 { 274 ESString sb = b.toStr(); 275 276 return ESBoolean.create(string.startsWith(sb.string)); 277 } 278 279 ESBoolean endsWith(ESBase b) throws Throwable 280 { 281 ESString sb = b.toStr(); 282 283 return ESBoolean.create(string.endsWith(sb.string)); 284 } 285 286 public boolean toBoolean() 287 { 288 return string.length() != 0; 289 } 290 291 static boolean isWhitespace(int ch) 292 { 293 switch (ch) { 294 case ' ': case '\t': case '\n': case '\r': case 0x0b: case '\f': 295 return true; 296 297 default: 298 return false; 299 } 300 } 301 302 static double checkTail(double value, ESString string, int i) 303 { 304 for (; i < string.length(); i++) { 305 if (! isWhitespace(string.charAt(i))) { 306 return 0.0/0.0; 307 } 308 } 309 310 return value; 311 } 312 313 static double parseFloat(ESString string, boolean hexOkay) 314 { 315 int len = string.length(); 316 317 int i = 0; 318 int ch = 0; 319 for (; i < len && isWhitespace(string.charAt(i)); i++) { 320 } 321 322 if (i >= len) 323 return hexOkay ? 0 : 0.0/0.0; 324 325 int radix = 10; 326 if (hexOkay && i + 1 < len && (ch = string.charAt(i)) == '0' && 327 ((ch = string.charAt(i + 1)) == 'x' || ch == 'X')) { 328 i += 2; 329 radix = 16; 330 } 331 332 int sign = 1; 333 if (radix == 10 && i < len && (ch = string.charAt(i)) == '+') { 334 i++; 335 } else if (radix == 10 && i < len && ch == '-') { 336 sign = -1; 337 i++; 338 } 339 340 if (radix == 10 && string.regionMatches(i, "Infinity", 0, 8)) { 341 if (hexOkay) 342 return checkTail(sign * (1.0/0.0), string, i + 8); 343 else 344 return sign * (1.0/0.0); 345 } 346 double value = 0.0; 347 boolean hasDigit = false; 348 for (; i < len; i++) { 349 ch = string.charAt(i); 350 351 if ('0' <= ch && ch <= '9') { 352 value = radix * value + string.charAt(i) - '0'; 353 hasDigit = true; 354 } else if (radix > 10 && ('a' <= ch && ch <= 'a' + radix - 11)) { 355 value = radix * value + string.charAt(i) - 'a' + 10; 356 hasDigit = true; 357 } else if (radix > 10 && ('A' <= ch && ch <= 'A' + radix - 11)) { 358 value = radix * value + string.charAt(i) - 'A' + 10; 359 hasDigit = true; 360 } else 361 break; 362 } 363 364 if (radix == 16 && ! hasDigit) 365 return 0.0/0.0; 366 else if (radix == 16) 367 return checkTail(value, string, i); 368 369 int expt = 0; 370 if (i < len && string.charAt(i) == '.') { 371 i++; 372 373 int power = 1; 374 for (; i < len && (ch = string.charAt(i)) >= '0' && ch <= '9'; i++) { 375 if (ch == '0') 376 power++; 377 else { 378 value = value * Math.pow(10, power) + ch - '0'; 379 expt -= power; 380 power = 1; 381 } 382 hasDigit = true; 383 } 384 } 385 386 if (! hasDigit) 387 return 0.0/0.0; 388 389 if (i < len && ((ch = string.charAt(i)) == 'e' || ch == 'E')) { 390 i++; 391 int exptSign = 1; 392 if (i < len && (ch = string.charAt(i)) == '+') 393 i++; 394 else if (i < len && ch == '-') { 395 exptSign = -1; 396 i++; 397 } 398 399 hasDigit = false; 400 401 int newExpt = 0; 402 for (; i < len && (ch = string.charAt(i)) >= '0' && ch <= '9'; i++) { 403 newExpt = 10 * newExpt + ch - '0'; 404 hasDigit = true; 405 } 406 407 if (! hasDigit) 408 return 0.0/0.0; 409 410 expt += exptSign * newExpt; 411 } 412 413 if (expt < 0) 414 value = sign * value / Math.pow(10.0, -expt); 415 else 416 value = sign * value * Math.pow(10.0, expt); 417 418 if (hexOkay) 419 return checkTail(value, string, i); 420 else 421 return value; 422 } 423 424 static double parseFloat(ESString string) 425 { 426 return parseFloat(string, false); 427 } 428 429 432 public String toString() 433 { 434 return string; 435 } 436 } 437 | Popular Tags |