1 33 package smallsql.database; 34 35 import java.sql.*; 36 37 52 final class LongTreeList { 53 54 55 155 156 157 private byte[] data; 158 private int size; 159 private int offset; 160 static final private int pointerSize = 3; 162 166 LongTreeList(){ 167 data = new byte[25]; 168 } 169 170 174 LongTreeList(long value) throws SQLException{ 175 this(); 176 add(value); 177 } 178 179 182 LongTreeList(MemoryStream input){ 183 int size = input.readInt(); 184 data = input.readBytes(size); 185 } 186 187 188 192 final void save(MemoryStream output){ 193 output.writeInt(size); 194 output.writeBytes(data, 0, size); 195 } 196 197 198 203 final void add(long value) throws SQLException{ 204 offset = 0; 205 if(size == 0){ 206 writeShort( (int)(value >> 48) ); 207 writePointer ( offset+pointerSize+2 ); 208 writeShort( 0 ); 209 writeShort( (int)(value >> 32) ); 210 writePointer ( offset+pointerSize+2 ); 211 writeShort( 0 ); 212 writeShort( (int)(value >> 16) ); 213 writePointer ( offset+pointerSize+2 ); 214 writeShort( 0 ); 215 writeShort( (int)(value) ); 216 writeShort( 0 ); 217 size = offset; 218 return; 219 } 220 int shift = 48; 221 boolean firstNode = (size > 2); while(shift>=0){ 223 int octet = (int)(value >> shift) & 0xFFFF; 224 while(true){ 225 int nextEntry = getUnsignedShort(); 226 if(nextEntry == octet){ 227 if(shift == 0) return; offset = getPointer(); 229 firstNode = true; 230 break; 231 } 232 if((nextEntry == 0 && !firstNode) || nextEntry > octet){ 233 offset -= 2; 234 while(true){ 235 if(shift != 0){ 236 offset = insertNode(octet); 237 }else{ 238 insertNodeLastLevel(octet); 239 return; 240 } 241 shift -= 16; 242 octet = (int)(value >> shift) & 0xFFFF; 243 } 244 } 245 firstNode = false; 246 if(shift != 0) offset += pointerSize; 247 } 248 shift -= 16; 249 } 250 } 251 252 253 258 final void remove(long value) throws SQLException{ 259 if(size == 0) return; 260 int offset1 = 0; 261 int offset2 = 0; 262 int offset3 = 0; 263 offset = 0; 264 int shift = 48; 265 boolean firstNode = true; boolean firstNode1 = true; 267 boolean firstNode2 = true; 268 boolean firstNode3 = true; 269 while(shift>=0){ 270 int octet = (int)(value >> shift) & 0xFFFF; 271 while(true){ 272 int nextEntry = getUnsignedShort(); 273 if(nextEntry == octet){ 274 if(shift == 0){ 275 offset -= 2; 277 removeNodeLastLevel(); 278 while(firstNode && getUnsignedShort() == 0){ 279 offset -= 2; 280 removeNodeLastLevel(); if(shift >= 3) 282 break; 283 offset = offset1; 284 offset1 = offset2; 285 offset2 = offset3; 286 firstNode = firstNode1; 287 firstNode1 = firstNode2; 288 firstNode2 = firstNode3; 289 removeNode(); 290 shift++; 291 } 292 return; 293 } 294 offset3 = offset2; 295 offset2 = offset1; 296 offset1 = offset -2; 297 offset = getPointer(); 298 firstNode3 = firstNode2; 299 firstNode2 = firstNode1; 300 firstNode1 = firstNode; 301 firstNode = true; 302 break; 303 } 304 if((nextEntry == 0 && !firstNode) || nextEntry > octet){ 305 return; 307 } 308 firstNode = false; 309 if(shift != 0) offset += pointerSize; 310 } 311 shift -= 16; 312 } 313 } 314 315 316 320 final long getNext(LongTreeListEnum listEnum){ 321 int shift = (3-listEnum.stack) << 4; 322 if(shift >= 64) return -1; offset = listEnum.offsetStack[listEnum.stack]; 324 long result = listEnum.resultStack[listEnum.stack]; 325 boolean firstNode = (offset == 0); while(true){ 327 int nextEntry = getUnsignedShort(); 328 if(nextEntry != 0 || firstNode){ 329 result |= (((long)nextEntry) << shift); 331 if(listEnum.stack>=3){ 332 listEnum.offsetStack[listEnum.stack] = offset; 333 return result; 334 } 335 listEnum.offsetStack[listEnum.stack] = offset+pointerSize; 336 offset = getPointer(); 337 shift -= 16; 338 listEnum.stack++; 339 listEnum.resultStack[listEnum.stack] = result; 340 firstNode = true; 341 }else{ 342 shift += 16; 344 listEnum.stack--; 345 if(listEnum.stack<0) return -1; result = listEnum.resultStack[listEnum.stack]; 347 offset = listEnum.offsetStack[listEnum.stack]; 348 firstNode = false; 349 } 350 } 351 } 352 353 354 358 final long getPrevious(LongTreeListEnum listEnum){ 359 int shift = (3-listEnum.stack) << 4; 360 if(shift >= 64){ shift = 48; 362 offset = 0; 363 listEnum.stack = 0; 364 listEnum.offsetStack[0] = 2 + pointerSize; 365 loopToEndOfNode(listEnum); 366 }else{ 367 setPreviousOffset(listEnum); 368 } 369 long result = listEnum.resultStack[listEnum.stack]; 370 while(true){ 371 int nextEntry = (offset < 0) ? -1 : getUnsignedShort(); 372 if(nextEntry >= 0){ 373 result |= (((long)nextEntry) << shift); 375 if(listEnum.stack>=3){ 376 listEnum.offsetStack[listEnum.stack] = offset; 377 return result; 378 } 379 listEnum.offsetStack[listEnum.stack] = offset+pointerSize; 380 offset = getPointer(); 381 shift -= 16; 382 listEnum.stack++; 383 listEnum.resultStack[listEnum.stack] = result; 384 loopToEndOfNode(listEnum); 385 }else{ 386 shift += 16; 388 listEnum.stack--; 389 if(listEnum.stack<0) return -1; result = listEnum.resultStack[listEnum.stack]; 391 setPreviousOffset(listEnum); 392 } 393 } 394 } 395 396 397 404 final private void setPreviousOffset(LongTreeListEnum listEnum){ 405 int previousOffset = listEnum.offsetStack[listEnum.stack] - 2*(2 + (listEnum.stack>=3 ? 0 : pointerSize)); 406 if(listEnum.stack == 0){ 407 offset = previousOffset; 408 return; 409 } 410 offset = listEnum.offsetStack[listEnum.stack-1] - pointerSize; 411 int pointer = getPointer(); 412 if(pointer <= previousOffset){ 413 offset = previousOffset; 414 return; 415 } 416 offset = -1; 417 } 418 419 420 423 final private void loopToEndOfNode(LongTreeListEnum listEnum){ 424 int nextEntry; 425 int nextOffset1, nextOffset2; 426 nextOffset1 = offset; 427 offset += 2; 428 if(listEnum.stack<3) 429 offset += pointerSize; 430 do{ 431 nextOffset2 = nextOffset1; 432 nextOffset1 = offset; 433 nextEntry = getUnsignedShort(); 434 if(listEnum.stack<3) 435 offset += pointerSize; 436 }while(nextEntry != 0); 437 offset = nextOffset2; 438 } 439 440 441 442 443 450 final private int insertNode(int octet) throws SQLException{ 451 int oldOffset = offset; 452 453 if(data.length < size + 4 + pointerSize) resize(); 454 System.arraycopy(data, oldOffset, data, oldOffset + 2+pointerSize, size-oldOffset); 455 size += 2+pointerSize; 456 457 writeShort( octet ); 458 writePointer( size ); 459 460 correctPointers( 0, oldOffset, 2+pointerSize, 0 ); 462 463 data[size++] = (byte)0; 464 data[size++] = (byte)0; 465 return size-2; 466 } 467 468 469 474 final private void insertNodeLastLevel(int octet) throws SQLException{ 475 int oldOffset = offset; 476 477 if(data.length < size + 2) resize(); 478 System.arraycopy(data, offset, data, offset + 2, size-offset); 479 size += 2; 480 writeShort( octet ); 481 482 correctPointers( 0, oldOffset, 2, 0 ); 484 } 485 486 487 492 final private void removeNode() throws SQLException{ 493 int oldOffset = offset; 494 495 correctPointers( 0, oldOffset, -(2+pointerSize), 0 ); 497 498 size -= 2+pointerSize; 499 System.arraycopy(data, oldOffset + 2+pointerSize, data, oldOffset, size-oldOffset); 500 501 offset = oldOffset; 502 } 503 504 505 510 final private void removeNodeLastLevel() throws SQLException{ 511 int oldOffset = offset; 512 513 correctPointers( 0, oldOffset, -2, 0 ); 515 516 size -= 2; 517 System.arraycopy(data, oldOffset + 2, data, oldOffset, size-oldOffset); 518 519 offset = oldOffset; 520 } 521 522 523 530 final private void correctPointers(int startOffset, int oldOffset, int diff, int level){ 531 offset = startOffset; 532 boolean firstNode = true; 533 while(offset < size){ 534 if(offset == oldOffset){ 535 int absDiff = Math.abs(diff); 536 if(absDiff == 2) return; 537 offset += absDiff; 538 firstNode = false; 539 continue; 540 } 541 int value = getUnsignedShort(); 542 if(value != 0 || firstNode){ 543 int pointer = getPointer(); 544 if(pointer > oldOffset){ 545 offset -= pointerSize; 546 writePointer( pointer + diff ); 547 if(diff > 0) pointer += diff; 548 } 549 if(level < 2){ 550 startOffset = offset; 551 correctPointers( pointer, oldOffset, diff, level+1); 552 offset = startOffset; 553 } 554 firstNode = false; 555 }else{ 556 return; 557 } 558 } 559 } 560 561 562 565 final private int getPointer(){ 566 int value = 0; 567 for(int i=0; i<pointerSize; i++){ 568 value <<= 8; 569 value += (data[offset++] & 0xFF); 570 } 571 return value; 572 } 573 574 575 578 final private void writePointer(int value){ 579 for(int i=pointerSize-1; i>=0; i--){ 580 data[offset++] = (byte)(value >> (i*8)); 581 } 582 } 583 584 585 588 final private int getUnsignedShort(){ 589 return ((data[ offset++ ] & 0xFF) << 8) | (data[ offset++ ] & 0xFF); 590 } 591 592 593 597 final private void writeShort(int value){ 598 data[offset++] = (byte)(value >> 8); 599 data[offset++] = (byte)(value); 600 } 601 602 603 606 private final void resize() throws SQLException{ 607 int newsize = data.length << 1; 608 if(newsize > 0xFFFFFF){ newsize = 0xFFFFFF; 610 if(newsize == data.length) throw Utils.createSQLException("To many equals entry in Index."); 611 } 612 byte[] temp = new byte[newsize]; 613 System.arraycopy(data, 0, temp, 0, data.length); 614 data = temp; 615 } 616 617 final int getSize() { 618 return size; 619 } 620 } 621 | Popular Tags |