1 module hunt.collection.HeapByteBuffer; 2 3 import hunt.collection.ByteBuffer; 4 import hunt.Exceptions; 5 6 import hunt.Integer; 7 import hunt.Long; 8 import hunt.Short; 9 10 import std.format; 11 12 /** 13 */ 14 class HeapByteBuffer : ByteBuffer { 15 16 // For speed these fields are actually declared in X-Buffer; 17 // these declarations are here as documentation 18 19 this(int cap, int lim) { // package-private 20 21 super(-1, 0, lim, cap, new byte[cap], 0); 22 /* 23 hb = new byte[cap]; 24 offset = 0; 25 */ 26 } 27 28 this(byte[] buf, int off, int len) { // package-private 29 30 super(-1, off, off + len, cast(int) buf.length, buf, 0); 31 /* 32 hb = buf; 33 offset = 0; 34 */ 35 } 36 37 protected this(byte[] buf, int mark, int pos, int lim, int cap, int off) { 38 39 super(mark, pos, lim, cap, buf, off); 40 /* 41 hb = buf; 42 offset = off; 43 */ 44 45 } 46 47 override ByteBuffer slice() { 48 return new HeapByteBuffer(hb, -1, 0, this.remaining(), 49 this.remaining(), this.position() + offset); 50 } 51 52 override ByteBuffer duplicate() { 53 return new HeapByteBuffer(hb, this.markValue(), this.position(), 54 this.limit(), this.capacity(), offset); 55 } 56 57 override ByteBuffer asReadOnlyBuffer() { 58 return new HeapByteBuffer(hb, this.markValue(), this.position(), 59 this.limit(), this.capacity(), offset); 60 } 61 62 override byte get() { 63 return hb[ix(nextGetIndex())]; 64 } 65 66 override byte get(int i) { 67 return hb[ix(checkIndex(i))]; 68 } 69 70 override ByteBuffer get(byte[] dst, int offset, int length) { 71 checkBounds(offset, length, cast(int) dst.length); 72 if (length > remaining()) 73 throw new BufferUnderflowException(""); 74 // System.arraycopy(hb, ix(position()), dst, offset, length); 75 int sourcePos = ix(position()); 76 dst[offset .. offset + length] = hb[sourcePos .. sourcePos + length]; 77 position(position() + length); 78 return this; 79 } 80 81 override bool isDirect() { 82 return false; 83 } 84 85 override bool isReadOnly() { 86 return false; 87 } 88 89 override ByteBuffer put(byte x) { 90 91 hb[ix(nextPutIndex())] = x; 92 return this; 93 94 } 95 96 override ByteBuffer put(int i, byte x) { 97 hb[ix(checkIndex(i))] = x; 98 return this; 99 } 100 101 override ByteBuffer put(byte[] src, int offset, int length) { 102 103 checkBounds(offset, length, cast(int) src.length); 104 105 if (length > remaining()) 106 throw new BufferOverflowException(); 107 int newPos = ix(position()); 108 hb[newPos .. newPos + length] = src[offset .. offset + length]; 109 110 position(position() + length); 111 return this; 112 113 } 114 115 override ByteBuffer put(ByteBuffer src) { 116 if (typeid(src) == typeid(HeapByteBuffer)) { 117 if (src is this) 118 throw new IllegalArgumentException(); 119 HeapByteBuffer sb = cast(HeapByteBuffer) src; 120 int n = sb.remaining(); 121 int r = this.remaining(); 122 if (n > r) 123 throw new BufferOverflowException(format("soure remaining: %d, this remaining: %d", n, r)); 124 125 int sourcePos = sb.ix(sb.position()); 126 int targetPos = ix(position()); 127 hb[targetPos .. targetPos + n] = sb.hb[sourcePos .. sourcePos + n]; 128 129 sb.position(sb.position() + n); 130 position(position() + n); 131 } else if (src.isDirect()) { 132 int n = src.remaining(); 133 if (n > remaining()) 134 throw new BufferOverflowException(""); 135 src.get(hb, ix(position()), n); 136 position(position() + n); 137 } else { 138 super.put(src); 139 } 140 return this; 141 142 } 143 144 // short 145 146 private static byte short1(short x) { 147 return cast(byte)(x >> 8); 148 } 149 150 private static byte short0(short x) { 151 return cast(byte)(x); 152 } 153 154 override short getShort() { 155 int index = ix(nextGetIndex(2)); 156 // short r = 0; 157 // short* ptr = &r; 158 // ptr[0]=hb[index+1]; // bigEndian 159 // ptr[1]=hb[index]; 160 // if (bigEndian) 161 // return makeShort(hb[index], hb[index + 1]); 162 // else 163 // return makeShort(hb[index + 1], hb[index]); 164 165 return convEndian(bigEndian, makeShort(hb[index], hb[index + 1])); 166 } 167 168 override short getShort(int i) { 169 int index = ix(checkIndex(i, 2)); 170 return convEndian(bigEndian, makeShort(hb[index], hb[index + 1])); 171 // if (bigEndian) 172 // return makeShort(hb[index], hb[index + 1]); 173 // else 174 // return makeShort(hb[index + 1], hb[index]); 175 } 176 177 override ByteBuffer putShort(short x) { 178 int index = ix(nextPutIndex(2)); 179 if (bigEndian) { 180 hb[index] = short1(x); 181 hb[index + 1] = short0(x); 182 } else { 183 hb[index] = short0(x); 184 hb[index + 1] = short1(x); 185 } 186 187 return this; 188 } 189 190 override ByteBuffer putShort(int i, short x) { 191 int index = ix(checkIndex(i, 2)); 192 if (bigEndian) { 193 hb[index] = short1(x); 194 hb[index + 1] = short0(x); 195 } else { 196 hb[index] = short0(x); 197 hb[index + 1] = short1(x); 198 } 199 return this; 200 } 201 202 // int 203 override int getInt() { 204 // auto index = ix(nextGetIndex(4)); 205 // return _getInt(index); 206 return getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian); 207 } 208 209 override int getInt(int i) { 210 // auto index = ix(checkIndex(i, 4)); 211 // return _getInt(index); 212 return getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian); 213 } 214 215 // private int _getInt(size_t index) { 216 // if (bigEndian) 217 // return makeInt(hb[index], hb[index + 1], hb[index + 2], hb[index + 3]); 218 // else 219 // return makeInt(hb[index + 3], hb[index + 2], hb[index + 1], hb[index]); 220 // } 221 222 // private static int makeInt(byte b3, byte b2, byte b1, byte b0) { 223 // return ((b3) << 24) | ((b2 & 0xff) << 16) | ((b1 & 0xff) << 8) | (b0 & 0xff); 224 // } 225 226 override ByteBuffer putInt(int x) { 227 putIntUnaligned(hb, ix(nextPutIndex(4)), x, bigEndian); 228 return this; 229 } 230 231 override ByteBuffer putInt(int i, int x) { 232 putIntUnaligned(hb, ix(checkIndex(i, 4)), x, bigEndian); 233 return this; 234 } 235 236 // long 237 238 override long getLong() { 239 return getLongUnaligned(hb, ix(nextGetIndex(8)), bigEndian); 240 } 241 242 override long getLong(int i) { 243 return getLongUnaligned(hb, ix(checkIndex(i, 8)), bigEndian); 244 } 245 246 override ByteBuffer putLong(long x) { 247 putLongUnaligned(hb, ix(nextPutIndex(8)), x, bigEndian); 248 return this; 249 } 250 251 override ByteBuffer putLong(int i, long x) { 252 putLongUnaligned(hb, ix(checkIndex(i, 8)), x, bigEndian); 253 return this; 254 } 255 256 // dfmt off 257 258 259 private static void putShortParts(byte[] buf, size_t offset, byte i0, byte i1) { 260 buf[offset + 0] = pick(i0, i1); 261 buf[offset + 1] = pick(i1, i0); 262 } 263 264 private static void putIntParts(byte[] buf, size_t offset, short i0, short i1) { 265 _putShort(buf, offset + 0, pick(i0, i1)); 266 _putShort(buf, offset + 2, pick(i1, i0)); 267 } 268 269 private static void putIntParts(byte[] buf, size_t offset, byte i0, byte i1, byte i2, byte i3) { 270 buf[offset + 0] = pick(i0, i3); 271 buf[offset + 1] = pick(i1, i2); 272 buf[offset + 2] = pick(i2, i1); 273 buf[offset + 3] = pick(i3, i0); 274 } 275 276 private static void putIntUnaligned(byte[] buf, size_t offset, int x) { 277 if ((offset & 3) == 0) { 278 _putInt(buf, offset, x); 279 } else if ((offset & 1) == 0) { 280 putIntParts(buf, offset, 281 cast(short)(x >> 0), 282 cast(short)(x >>> 16)); 283 } else { 284 putIntParts(buf, offset, 285 cast(byte)(x >>> 0), 286 cast(byte)(x >>> 8), 287 cast(byte)(x >>> 16), 288 cast(byte)(x >>> 24)); 289 } 290 } 291 292 private static void putIntUnaligned(byte[] buf, size_t offset, int x, bool bigEndian) { 293 putIntUnaligned(buf, offset, convEndian(bigEndian, x)); 294 } 295 296 297 private static int getIntUnaligned(byte[] buf, size_t offset) { 298 if ((offset & 3) == 0) { 299 return _getInt(buf, offset); 300 } else if ((offset & 1) == 0) { 301 return makeInt(_getShort(buf, offset), 302 _getShort(buf, offset + 2)); 303 } else { 304 return makeInt(buf[offset], 305 buf[offset + 1], 306 buf[offset + 2], 307 buf[offset + 3]); 308 } 309 } 310 311 private static int getIntUnaligned(byte[] buf, size_t offset, bool bigEndian) { 312 return convEndian(bigEndian, getIntUnaligned(buf, offset)); 313 } 314 315 /** 316 * Fetches a value at some byte offset into a given Java object. 317 * More specifically, fetches a value within the given object 318 * <code>o</code> at the given offset, or (if <code>o</code> is 319 * null) from the memory address whose numerical value is the 320 * given offset. <p> 321 * 322 * The specification of this method is the same as {@link 323 * #getLong(Object, long)} except that the offset does not need to 324 * have been obtained from {@link #objectFieldOffset} on the 325 * {@link java.lang.reflect.Field} of some Java field. The value 326 * in memory is raw data, and need not correspond to any Java 327 * variable. Unless <code>o</code> is null, the value accessed 328 * must be entirely within the allocated object. The endianness 329 * of the value in memory is the endianness of the native platform. 330 * 331 * <p> The read will be atomic with respect to the largest power 332 * of two that divides the GCD of the offset and the storage size. 333 * For example, getLongUnaligned will make atomic reads of 2-, 4-, 334 * or 8-byte storage units if the offset is zero mod 2, 4, or 8, 335 * respectively. There are no other guarantees of atomicity. 336 * <p> 337 * 8-byte atomicity is only guaranteed on platforms on which 338 * support atomic accesses to longs. 339 * 340 * @param o Java heap object in which the value resides, if any, else 341 * null 342 * @param offset The offset in bytes from the start of the object 343 * @return the value fetched from the indicated object 344 * @throws RuntimeException No defined exceptions are thrown, not even 345 * {@link NullPointerException} 346 */ 347 private static long getLongUnaligned(byte[] buf, size_t offset) { 348 if ((offset & 7) == 0) { 349 return _getLong(buf, offset); 350 } else if ((offset & 3) == 0) { 351 return makeLong(_getInt(buf, offset), 352 _getInt(buf, offset + 4)); 353 } else if ((offset & 1) == 0) { 354 return makeLong(_getShort(buf, offset), 355 _getShort(buf, offset + 2), 356 _getShort(buf, offset + 4), 357 _getShort(buf, offset + 6)); 358 } else { 359 return makeLong(buf[offset], 360 buf[offset + 1], 361 buf[offset + 2], 362 buf[offset + 3], 363 buf[offset + 4], 364 buf[offset + 5], 365 buf[offset + 6], 366 buf[offset + 7]); 367 } 368 } 369 370 /** 371 * As {@link #getLongUnaligned(Object, long)} but with an 372 * additional argument which specifies the endianness of the value 373 * as stored in memory. 374 * 375 * @param o Java heap object in which the variable resides 376 * @param offset The offset in bytes from the start of the object 377 * @param bigEndian The endianness of the value 378 * @return the value fetched from the indicated object 379 */ 380 private static long getLongUnaligned(byte[] hb, size_t offset, bool bigEndian) { 381 return convEndian(bigEndian, getLongUnaligned(hb, offset)); 382 } 383 384 /** 385 * As {@link #putLongUnaligned(Object, long, long)} but with an additional 386 * argument which specifies the endianness of the value as stored in memory. 387 * @param o Java heap object in which the value resides 388 * @param offset The offset in bytes from the start of the object 389 * @param x the value to store 390 * @param bigEndian The endianness of the value 391 * @throws RuntimeException No defined exceptions are thrown, not even 392 * {@link NullPointerException} 393 */ 394 private static void putLongUnaligned(byte[] buf, size_t offset, long x, bool bigEndian) { 395 putLongUnaligned(buf, offset, convEndian(bigEndian, x)); 396 } 397 398 // These methods write integers to memory from smaller parts 399 // provided by their caller. The ordering in which these parts 400 // are written is the native endianness of this platform. 401 private static void putLongParts(byte[] buf, size_t offset, byte i0, byte i1, byte i2, 402 byte i3, byte i4, byte i5, byte i6, byte i7) { 403 buf[offset + 0] = pick(i0, i7); 404 buf[offset + 1] = pick(i1, i6); 405 buf[offset + 2] = pick(i2, i5); 406 buf[offset + 3] = pick(i3, i4); 407 buf[offset + 4] = pick(i4, i3); 408 buf[offset + 5] = pick(i5, i2); 409 buf[offset + 6] = pick(i6, i1); 410 buf[offset + 7] = pick(i7, i0); 411 } 412 413 private static void putLongParts(byte[] buf, size_t offset, short i0, short i1, short i2, short i3) { 414 _putShort(buf, offset + 0, pick(i0, i3)); 415 _putShort(buf, offset + 2, pick(i1, i2)); 416 _putShort(buf, offset + 4, pick(i2, i1)); 417 _putShort(buf, offset + 6, pick(i3, i0)); 418 } 419 420 private static void putLongParts(byte[] buf, size_t offset, int i0, int i1) { 421 _putInt(buf, offset + 0, pick(i0, i1)); 422 _putInt(buf, offset + 4, pick(i1, i0)); 423 } 424 425 private static void putLongUnaligned(byte[] hb, size_t offset, long x) { 426 if ((offset & 7) == 0) { 427 _putLong(hb, offset, x); 428 } else if ((offset & 3) == 0) { 429 putLongParts(hb, offset, 430 cast(int)(x >> 0), 431 cast(int)(x >>> 32)); 432 } else if ((offset & 1) == 0) { 433 putLongParts(hb, offset, 434 cast(short)(x >>> 0), 435 cast(short)(x >>> 16), 436 cast(short)(x >>> 32), 437 cast(short)(x >>> 48)); 438 } else { 439 putLongParts(hb, offset, 440 cast(byte)(x >>> 0), 441 cast(byte)(x >>> 8), 442 cast(byte)(x >>> 16), 443 cast(byte)(x >>> 24), 444 cast(byte)(x >>> 32), 445 cast(byte)(x >>> 40), 446 cast(byte)(x >>> 48), 447 cast(byte)(x >>> 56)); 448 } 449 } 450 451 private static short _getShort(byte[] buf, size_t offset) { 452 short* ptr = cast(short*)(buf.ptr + offset); 453 return *ptr; 454 } 455 456 private static void _putShort(byte[] buf, size_t offset, short x) { 457 buf[offset] = short0(x); 458 buf[offset + 1] = short1(x); 459 } 460 461 private static int _getInt(byte[] buf, size_t offset) { 462 int* ptr = cast(int*)(buf.ptr + offset); 463 return *ptr; 464 } 465 466 private static void _putInt(byte[] buf, size_t offset, int x) { 467 buf[offset] = int0(x); 468 buf[offset + 1] = int1(x); 469 buf[offset + 2] = int2(x); 470 buf[offset + 3] = int3(x); 471 } 472 473 private static long _getLong(byte[] buf, size_t offset) { 474 long* ptr = cast(long*)(buf.ptr + offset); 475 return *ptr; 476 } 477 478 private static void _putLong(byte[] buf, size_t offset, long x) { 479 buf[offset] = long0(x); 480 buf[offset + 1] = long1(x); 481 buf[offset + 2] = long2(x); 482 buf[offset + 3] = long3(x); 483 484 buf[offset + 4] = long4(x); 485 buf[offset + 5] = long5(x); 486 buf[offset + 6] = long6(x); 487 buf[offset + 7] = long7(x); 488 } 489 490 private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { 491 return ((toUnsignedLong(i0) << pickPos(56, 0)) 492 | (toUnsignedLong(i1) << pickPos(56, 8)) 493 | (toUnsignedLong(i2) << pickPos(56, 16)) 494 | (toUnsignedLong(i3) << pickPos(56, 24)) 495 | (toUnsignedLong(i4) << pickPos(56, 32)) 496 | (toUnsignedLong(i5) << pickPos(56, 40)) 497 | (toUnsignedLong(i6) << pickPos(56, 48)) 498 | (toUnsignedLong(i7) << pickPos(56, 56))); 499 } 500 501 private static long makeLong(short i0, short i1, short i2, short i3) { 502 return ((toUnsignedLong(i0) << pickPos(48, 0)) 503 | (toUnsignedLong(i1) << pickPos(48, 16)) 504 | (toUnsignedLong(i2) << pickPos(48, 32)) 505 | (toUnsignedLong(i3) << pickPos(48, 48))); 506 } 507 508 private static long makeLong(int i0, int i1) { 509 return (toUnsignedLong(i0) << pickPos(32, 0)) 510 | (toUnsignedLong(i1) << pickPos(32, 32)); 511 } 512 513 private static int makeInt(short i0, short i1) { 514 return (toUnsignedInt(i0) << pickPos(16, 0)) 515 | (toUnsignedInt(i1) << pickPos(16, 16)); 516 } 517 518 private static int makeInt(byte i0, byte i1, byte i2, byte i3) { 519 return ((toUnsignedInt(i0) << pickPos(24, 0)) 520 | (toUnsignedInt(i1) << pickPos(24, 8)) 521 | (toUnsignedInt(i2) << pickPos(24, 16)) 522 | (toUnsignedInt(i3) << pickPos(24, 24))); 523 } 524 525 static short makeShort(byte i0, byte i1) { 526 return cast(short)((toUnsignedInt(i0) << pickPos(8, 0)) 527 | (toUnsignedInt(i1) << pickPos(8, 8))); 528 } 529 530 version (LittleEndian) { 531 // Maybe byte-reverse an integer 532 // private static char convEndian(bool big, char n) { return big == BE ? n : Char.reverseBytes(n); } 533 private static short convEndian(bool big, short n) { return big ? Short.reverseBytes(n) : n ; } 534 private static int convEndian(bool big, int n) { return big ? Integer.reverseBytes(n) : n ; } 535 private static long convEndian(bool big, long n) { return big ? Long.reverseBytes(n) : n ; } 536 537 private static byte pick(byte le, byte be) { return le; } 538 private static short pick(short le, short be) { return le; } 539 private static int pick(int le, int be) { return le; } 540 541 private static int pickPos(int top, int pos) { return pos; } 542 } else { 543 // Maybe byte-reverse an integer 544 // private static char convEndian(bool big, char n) { return big == BE ? n : Character.reverseBytes(n); } 545 private static short convEndian(bool big, short n) { return big ? n : Short.reverseBytes(n) ; } 546 private static int convEndian(bool big, int n) { return big ? n : Integer.reverseBytes(n) ; } 547 private static long convEndian(bool big, long n) { return big ? n : Long.reverseBytes(n) ; } 548 549 private static byte pick(byte le, byte be) { return be; } 550 private static short pick(short le, short be) { return be; } 551 private static int pick(int le, int be) { return be; } 552 553 private static int pickPos(int top, int pos) { return top - pos; } 554 } 555 556 // Zero-extend an integer 557 private static int toUnsignedInt(byte n) { return n & 0xff; } 558 private static int toUnsignedInt(short n) { return n & 0xffff; } 559 private static long toUnsignedLong(byte n) { return n & 0xffL; } 560 private static long toUnsignedLong(short n) { return n & 0xffffL; } 561 private static long toUnsignedLong(int n) { return n & 0xffffffffL; } 562 563 // private static byte short1(short x) { return cast(byte)(x >> 8); } 564 // private static byte short0(short x) { return cast(byte)(x ); } 565 566 private static byte int3(int x) { return cast(byte)(x >> 24); } 567 private static byte int2(int x) { return cast(byte)(x >> 16); } 568 private static byte int1(int x) { return cast(byte)(x >> 8); } 569 private static byte int0(int x) { return cast(byte)(x ); } 570 571 private static byte long7(long x) { return cast(byte)(x >> 56); } 572 private static byte long6(long x) { return cast(byte)(x >> 48); } 573 private static byte long5(long x) { return cast(byte)(x >> 40); } 574 private static byte long4(long x) { return cast(byte)(x >> 32); } 575 private static byte long3(long x) { return cast(byte)(x >> 24); } 576 private static byte long2(long x) { return cast(byte)(x >> 16); } 577 private static byte long1(long x) { return cast(byte)(x >> 8); } 578 private static byte long0(long x) { return cast(byte)(x ); } 579 580 // dfmt on 581 582 override ByteBuffer compact() { 583 int sourceIndex = ix(position()); 584 int targetIndex = ix(0); 585 int len = remaining(); 586 // tracef("hb.length=%d, remaining=%d, targetIndex=%d, sourceIndex=%d", hb.length, len, targetIndex, sourceIndex) ; 587 if(targetIndex != sourceIndex) { 588 hb[targetIndex .. targetIndex + len] = hb[sourceIndex .. sourceIndex + len]; 589 position(len); 590 limit(capacity()); 591 discardMark(); 592 } 593 return this; 594 595 } 596 }