1 21 22 package org.armedbear.lisp; 23 24 public final class ComplexString extends AbstractString 25 { 26 private int capacity; 27 private int fillPointer = -1; private boolean isDisplaced; 29 30 private char[] chars; 32 33 private AbstractArray array; 35 private int displacement; 36 37 public ComplexString(int capacity) 38 { 39 this.capacity = capacity; 40 chars = new char[capacity]; 41 isDisplaced = false; 42 } 43 44 public ComplexString(int capacity, AbstractArray array, int displacement) 45 { 46 this.capacity = capacity; 47 this.array = array; 48 this.displacement = displacement; 49 isDisplaced = true; 50 } 51 52 public LispObject typeOf() 53 { 54 return list2(Symbol.STRING, number(capacity())); 55 } 56 57 public LispClass classOf() 58 { 59 return BuiltInClass.STRING; 60 } 61 62 public boolean hasFillPointer() 63 { 64 return fillPointer >= 0; 65 } 66 67 public int getFillPointer() 68 { 69 return fillPointer; 70 } 71 72 public void setFillPointer(int n) 73 { 74 fillPointer = n; 75 } 76 77 public void setFillPointer(LispObject obj) throws ConditionThrowable 78 { 79 if (obj == T) 80 fillPointer = capacity(); 81 else { 82 int n = Fixnum.getValue(obj); 83 if (n > capacity()) { 84 StringBuffer sb = new StringBuffer ("The new fill pointer ("); 85 sb.append(n); 86 sb.append(") exceeds the capacity of the vector ("); 87 sb.append(capacity()); 88 sb.append(")."); 89 signal(new LispError(sb.toString())); 90 } else if (n < 0) { 91 StringBuffer sb = new StringBuffer ("The new fill pointer ("); 92 sb.append(n); 93 sb.append(") is negative."); 94 signal(new LispError(sb.toString())); 95 } else 96 fillPointer = n; 97 } 98 } 99 100 public boolean isDisplaced() 101 { 102 return isDisplaced; 103 } 104 105 public LispObject arrayDisplacement() throws ConditionThrowable 106 { 107 LispObject value1, value2; 108 if (array != null) { 109 value1 = array; 110 value2 = new Fixnum(displacement); 111 } else { 112 value1 = NIL; 113 value2 = Fixnum.ZERO; 114 } 115 return LispThread.currentThread().setValues(value1, value2); 116 } 117 118 public char[] chars() throws ConditionThrowable 119 { 120 if (chars != null) 121 return chars; 122 Debug.assertTrue(array != null); 123 char[] chars = new char[capacity]; 124 System.arraycopy(array.chars(), displacement, chars, 0, capacity); 125 return chars; 126 } 127 128 public char[] getStringChars() throws ConditionThrowable 129 { 130 if (fillPointer < 0) 131 return chars(); 132 char[] ret = new char[fillPointer]; 133 System.arraycopy(chars(), 0, ret, 0, fillPointer); 134 return ret; 135 } 136 137 public boolean equal(LispObject obj) throws ConditionThrowable 138 { 139 if (this == obj) 140 return true; 141 if (obj instanceof AbstractString) { 142 AbstractString string = (AbstractString) obj; 143 if (string.length() != length()) 144 return false; 145 for (int i = length(); i-- > 0;) 146 if (string.getChar(i) != getChar(i)) 147 return false; 148 return true; 149 } 150 if (obj instanceof NilVector) 151 return obj.equal(this); 152 return false; 153 } 154 155 public boolean equalp(LispObject obj) throws ConditionThrowable 156 { 157 if (this == obj) 158 return true; 159 if (obj instanceof AbstractString) { 160 AbstractString string = (AbstractString) obj; 161 if (string.length() != length()) 162 return false; 163 for (int i = length(); i-- > 0;) { 164 if (string.getChar(i) != getChar(i)) { 165 if (Utilities.toLowerCase(string.getChar(i)) != Utilities.toLowerCase(getChar(i))) 166 return false; 167 } 168 } 169 return true; 170 } 171 if (obj instanceof AbstractArray) 172 return obj.equalp(this); 173 return false; 174 } 175 176 public LispObject subseq(int start, int end) throws ConditionThrowable 177 { 178 SimpleString s = new SimpleString(end - start); 179 int i = start, j = 0; 180 while (i < end) 181 s.setChar(j++, getChar(i++)); 182 return s; 183 } 184 185 public void fill(LispObject obj) throws ConditionThrowable 186 { 187 fill(LispCharacter.getValue(obj)); 188 } 189 190 public void fill(char c) throws ConditionThrowable 191 { 192 for (int i = length(); i-- > 0;) 193 setChar(i, c); 194 } 195 196 public void shrink(int n) throws ConditionThrowable 197 { 198 if (chars != null) { 199 if (n < capacity) { 200 char[] newArray = new char[n]; 201 System.arraycopy(chars, 0, newArray, 0, n); 202 chars = newArray; 203 capacity = n; 204 return; 205 } 206 if (n == capacity) 207 return; 208 } 209 signal(new LispError()); 210 } 211 212 public LispObject reverse() throws ConditionThrowable 213 { 214 int length = length(); 215 SimpleString result = new SimpleString(length); 216 int i, j; 217 for (i = 0, j = length - 1; i < length; i++, j--) 218 result.setChar(i, getChar(j)); 219 return result; 220 } 221 222 public LispObject nreverse() throws ConditionThrowable 223 { 224 int i = 0; 225 int j = length() - 1; 226 while (i < j) { 227 char temp = getChar(i); 228 setChar(i, getChar(j)); 229 setChar(j, temp); 230 ++i; 231 --j; 232 } 233 return this; 234 } 235 236 public LispObject getRowMajor(int index) throws ConditionThrowable 237 { 238 return LispCharacter.getInstance(getChar(index)); 239 } 240 241 public void setRowMajor(int index, LispObject newValue) throws ConditionThrowable 242 { 243 setChar(index, LispCharacter.getValue(newValue)); 244 } 245 246 public char getChar(int index) throws ConditionThrowable 247 { 248 if (chars != null) { 249 try { 250 return chars[index]; 251 } 252 catch (ArrayIndexOutOfBoundsException e) { 253 badIndex(index, capacity); 254 return 0; } 256 } else 257 return LispCharacter.getValue(array.getRowMajor(index + displacement)); 258 } 259 260 public void setChar(int index, char c) throws ConditionThrowable 261 { 262 if (chars != null) { 263 try { 264 chars[index] = c; 265 } 266 catch (ArrayIndexOutOfBoundsException e) { 267 badIndex(index, capacity); 268 } 269 } else 270 array.setRowMajor(index + displacement, LispCharacter.getInstance(c)); 271 } 272 273 public String getStringValue() throws ConditionThrowable 274 { 275 if (fillPointer >= 0) 276 return new String (chars(), 0, fillPointer); 277 else 278 return new String (chars()); 279 } 280 281 public Object javaInstance() throws ConditionThrowable 282 { 283 return new String (chars()); 284 } 285 286 public Object javaInstance(Class c) throws ConditionThrowable 287 { 288 return javaInstance(); 289 } 290 291 public final int capacity() 292 { 293 return capacity; 294 } 295 296 public AbstractVector adjustVector(int newCapacity, 297 LispObject initialElement, 298 LispObject initialContents) 299 throws ConditionThrowable 300 { 301 if (initialContents != NIL) { 302 char[] newChars = new char[newCapacity]; 306 if (initialContents.listp()) { 307 LispObject list = initialContents; 308 for (int i = 0; i < newCapacity; i++) { 309 newChars[i] = LispCharacter.getValue(list.car()); 310 list = list.cdr(); 311 } 312 } else if (initialContents.vectorp()) { 313 for (int i = 0; i < newCapacity; i++) 314 newChars[i] = LispCharacter.getValue(initialContents.elt(i)); 315 } else 316 signal(new TypeError(initialContents, Symbol.SEQUENCE)); 317 chars = newChars; 318 } else { 319 if (chars == null) { 320 chars = new char[newCapacity]; 322 final int limit = Math.min(capacity, newCapacity); 323 if (array instanceof AbstractString) { 324 AbstractString string = (AbstractString) array; 325 for (int i = 0; i < limit; i++) { 326 chars[i] = string.getChar(displacement + i); 327 } 328 } else { 329 for (int i = 0; i < limit; i++) { 330 LispCharacter character = 331 (LispCharacter) array.getRowMajor(displacement + i); 332 chars[i] = character.value; 333 } 334 } 335 } else if (capacity != newCapacity) { 336 char[] newElements = new char[newCapacity]; 337 System.arraycopy(chars, 0, newElements, 0, 338 Math.min(capacity, newCapacity)); 339 chars = newElements; 340 } 341 if (initialElement != NIL && capacity < newCapacity) { 342 final char c = LispCharacter.getValue(initialElement); 344 for (int i = capacity; i < newCapacity; i++) 345 chars[i] = c; 346 } 347 } 348 capacity = newCapacity; 349 array = null; 350 displacement = 0; 351 isDisplaced = false; 352 return this; 353 } 354 355 public AbstractVector adjustVector(int newCapacity, 356 AbstractArray displacedTo, 357 int displacement) 358 throws ConditionThrowable 359 { 360 capacity = newCapacity; 361 array = displacedTo; 362 this.displacement = displacement; 363 chars = null; 364 isDisplaced = true; 365 return this; 366 } 367 368 public final int length() 369 { 370 return fillPointer >= 0 ? fillPointer : capacity; 371 } 372 373 public LispObject elt(int index) throws ConditionThrowable 374 { 375 final int limit = length(); 376 if (index < 0 || index >= limit) 377 badIndex(index, limit); 378 return LispCharacter.getInstance(getChar(index)); 379 } 380 381 public LispObject AREF(LispObject index) throws ConditionThrowable 383 { 384 return LispCharacter.getInstance(getChar(Fixnum.getValue(index))); 385 } 386 387 public LispObject vectorPushExtend(LispObject element) 388 throws ConditionThrowable 389 { 390 if (fillPointer < 0) 391 noFillPointer(); 392 if (fillPointer >= capacity) { 393 ensureCapacity(capacity * 2 + 1); 395 } 396 if (chars != null) { 397 try { 398 chars[fillPointer] = ((LispCharacter)element).value; 399 } 400 catch (ClassCastException e) { 401 signal(new TypeError(element, Symbol.CHARACTER)); 402 } 403 } else 404 array.setRowMajor(fillPointer + displacement, element); 405 return new Fixnum(fillPointer++); 406 } 407 408 public LispObject vectorPushExtend(LispObject element, LispObject extension) 409 throws ConditionThrowable 410 { 411 int ext = Fixnum.getValue(extension); 412 if (fillPointer < 0) 413 noFillPointer(); 414 if (fillPointer >= capacity) { 415 ext = Math.max(ext, capacity + 1); 417 ensureCapacity(capacity + ext); 418 } 419 if (chars != null) { 420 try { 421 chars[fillPointer] = ((LispCharacter)element).value; 422 } 423 catch (ClassCastException e) { 424 signal(new TypeError(element, Symbol.CHARACTER)); 425 } 426 } else 427 array.setRowMajor(fillPointer + displacement, element); 428 return new Fixnum(fillPointer++); 429 } 430 431 public final void ensureCapacity(int minCapacity) throws ConditionThrowable 432 { 433 if (chars != null) { 434 if (capacity < minCapacity) { 435 char[] newArray = new char[minCapacity]; 436 System.arraycopy(chars, 0, newArray, 0, capacity); 437 chars = newArray; 438 capacity = minCapacity; 439 } 440 } else { 441 Debug.assertTrue(array != null); 442 if (array.getTotalSize() - displacement < minCapacity) { 443 chars = new char[minCapacity]; 445 final int limit = array.getTotalSize() - displacement; 446 if (array instanceof AbstractString) { 447 AbstractString string = (AbstractString) array; 448 for (int i = 0; i < limit; i++) { 449 chars[i] = string.getChar(displacement + i); 450 } 451 } else { 452 for (int i = 0; i < limit; i++) { 453 LispCharacter character = 454 (LispCharacter) array.getRowMajor(displacement + i); 455 chars[i] = character.value; 456 } 457 } 458 capacity = minCapacity; 459 array = null; 460 displacement = 0; 461 isDisplaced = false; 462 } 463 } 464 } 465 466 public int hashCode() 467 { 468 int hashCode = 0; 469 try { 470 final int limit = length(); 471 for (int i = 0; i < limit; i++) 472 hashCode = hashCode * 31 + getChar(i); 473 } 474 catch (ConditionThrowable t) { 475 Debug.trace(t); 477 } 478 return hashCode; 479 } 480 } 481 | Popular Tags |