1 57 58 package org.enhydra.apache.xerces.utils; 59 60 import org.enhydra.apache.xerces.readers.XMLEntityHandler; 61 62 71 public final class CharDataChunk implements StringPool.StringProducer { 72 77 public static final int CHUNK_SHIFT = 14; public static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); 79 public static final int CHUNK_MASK = CHUNK_SIZE - 1; 80 91 public static CharDataChunk createChunk(StringPool stringPool, CharDataChunk prev) { 92 93 CharDataChunk newChunk = null; 94 synchronized (CharDataChunk.class) { 95 newChunk = fgFreeChunks; 96 if (newChunk != null) { 97 fgFreeChunks = newChunk.fNextChunk; 98 } else { 99 newChunk = new CharDataChunk(); 100 } 101 } 102 newChunk.fStringPool = stringPool; 103 newChunk.fRefCount = 1; newChunk.fChunk = prev == null ? 0 : prev.fChunk + 1; 105 newChunk.fNextChunk = null; 106 newChunk.fPreviousChunk = prev; 107 if (prev != null) { 108 prev.setNextChunk(newChunk); 130 } 131 return newChunk; 132 } 133 144 public CharDataChunk chunkFor(int offset) { 145 int firstChunk = offset >> CHUNK_SHIFT; 146 if (firstChunk == fChunk) 147 return this; 148 CharDataChunk dataChunk = fPreviousChunk; 149 while (firstChunk != dataChunk.fChunk) 150 dataChunk = dataChunk.fPreviousChunk; 151 return dataChunk; 152 } 153 163 public char[] toCharArray() { 164 return fData; 165 } 166 171 public void setCharArray(char[] data) { 172 fData = data; 173 } 174 180 public CharDataChunk nextChunk() { 181 return fNextChunk; 182 } 183 197 public boolean clearPreviousChunk() { 198 if (fPreviousChunk != null) { 199 fPreviousChunk.clearNextChunk(); 200 fPreviousChunk.removeRef(); 201 fPreviousChunk = null; 202 return true; 203 } 204 return false; 205 } 206 211 public void releaseChunk() { 212 removeRef(); 213 } 214 221 public int addString(int offset, int length) { 222 int chunk = offset >> CHUNK_SHIFT; 223 if (chunk != fChunk) { 224 if (fPreviousChunk == null) 225 throw new RuntimeException (new ImplementationMessages().createMessage(null, ImplementationMessages.INT_PCN, 0, null)); 226 return fPreviousChunk.addString(offset, length); 227 } 228 int lastChunk = (offset + length - 1) >> CHUNK_SHIFT; 229 if (chunk == lastChunk) { 230 addRef(); 231 return fStringPool.addString(this, offset & CHUNK_MASK, length); 232 } 233 String str = toString(offset & CHUNK_MASK, length); 234 return fStringPool.addString(str); 235 } 236 244 public int addSymbol(int offset, int length, int hashcode) { 245 int chunk = offset >> CHUNK_SHIFT; 246 if (chunk != fChunk) { 247 if (fPreviousChunk == null) 248 throw new RuntimeException (new ImplementationMessages().createMessage(null, ImplementationMessages.INT_PCN, 0, null)); 249 return fPreviousChunk.addSymbol(offset, length, hashcode); 250 } 251 int lastChunk = (offset + length - 1) >> CHUNK_SHIFT; 252 int index = offset & CHUNK_MASK; 253 if (chunk == lastChunk) { 254 if (hashcode == 0) 255 hashcode = StringHasher.hashChars(fData, index, length); 256 int symbol = fStringPool.lookupSymbol(this, offset & CHUNK_MASK, length, hashcode); 257 if (symbol == -1) { 258 String str = toString(offset & CHUNK_MASK, length); 259 symbol = fStringPool.addNewSymbol(str, hashcode); 260 } 261 return symbol; 262 } 263 String str = toString(offset & CHUNK_MASK, length); 264 return fStringPool.addSymbol(str); 265 } 266 273 public void append(XMLEntityHandler.CharBuffer charBuffer, int offset, int length) { 274 CharDataChunk dataChunk = chunkFor(offset); 278 int index = offset & CHUNK_MASK; 279 int nbytes = (index + length <= CHUNK_SIZE) ? length : CHUNK_SIZE - index; 280 while (true) { 284 charBuffer.append(dataChunk.fData, index, nbytes); 285 length -= nbytes; 286 if (length == 0) 287 break; 288 dataChunk = dataChunk.fNextChunk; 289 index = 0; 290 nbytes = length <= CHUNK_SIZE ? length : CHUNK_SIZE; 291 } 292 } 293 303 public String toString(int offset, int length) { 304 if (offset + length <= CHUNK_SIZE) { 305 return new String (fData, offset, length); 309 } 310 StringBuffer sb = new StringBuffer (length); 314 int nbytes = CHUNK_SIZE - offset; 318 sb.append(fData, offset, nbytes); 319 length -= nbytes; 320 CharDataChunk aChunk = fNextChunk; 324 do { 325 nbytes = length <= CHUNK_SIZE ? length : CHUNK_SIZE; 326 sb.append(aChunk.fData, 0, nbytes); 327 length -= nbytes; 328 aChunk = aChunk.fNextChunk; 329 } while (length > 0); 330 String retval = sb.toString(); 331 sb = null; return retval; 333 } 334 340 public void releaseString(int offset, int length) { 341 removeRef(); 342 } 343 353 public boolean equalsString(int offset, int length, char[] strChars, int strOffset, int strLength) { 354 if (length != strLength) 355 return false; 356 if (offset + length <= CHUNK_SIZE) { 357 for (int i = 0; i < length; i++) { 361 if (fData[offset++] != strChars[strOffset++]) 362 return false; 363 } 364 return true; 365 } 366 int nbytes = CHUNK_SIZE - offset; 370 length -= nbytes; 371 while (nbytes-- > 0) { 372 if (fData[offset++] != strChars[strOffset++]) 373 return false; 374 } 375 CharDataChunk aChunk = fNextChunk; 379 do { 380 offset = 0; 381 nbytes = length <= CHUNK_SIZE ? length : CHUNK_SIZE; 382 length -= nbytes; 383 while (nbytes-- > 0) { 384 if (aChunk.fData[offset++] != strChars[strOffset++]) 385 return false; 386 } 387 aChunk = aChunk.fNextChunk; 388 } while (length > 0); 389 return true; 390 } 391 395 private CharDataChunk() {} 399 private void addRef() { 403 fRefCount++; 404 } 405 private void removeRef() { 409 fRefCount--; 410 if (fRefCount == 0) { 411 fStringPool = null; 412 fChunk = -1; 413 fPreviousChunk = null; 414 synchronized (CharDataChunk.class) { 415 418 fNextChunk = null; 419 fgFreeChunks = this; 420 } 421 } 422 } 423 private void clearNextChunk() { 427 if (fNextChunk != null) 428 fNextChunk.removeRef(); 429 fNextChunk = null; 430 } 431 private void setNextChunk(CharDataChunk nextChunk) { 435 if (fNextChunk != null) { 436 throw new RuntimeException ("CharDataChunk::setNextChunk"); 437 } 438 nextChunk.addRef(); 439 fNextChunk = nextChunk; 440 } 441 private StringPool fStringPool; 445 private int fRefCount; 446 private int fChunk; 447 private char[] fData = null; 448 private CharDataChunk fNextChunk; 449 private CharDataChunk fPreviousChunk; 450 private static CharDataChunk fgFreeChunks = null; 451 } 452 | Popular Tags |