1 module hunt.io.HeapByteBuffer; 2 3 import hunt.io.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 private static long getLongUnaligned(byte[] buf, size_t offset) { 316 if ((offset & 7) == 0) { 317 return _getLong(buf, offset); 318 } else if ((offset & 3) == 0) { 319 return makeLong(_getInt(buf, offset), 320 _getInt(buf, offset + 4)); 321 } else if ((offset & 1) == 0) { 322 return makeLong(_getShort(buf, offset), 323 _getShort(buf, offset + 2), 324 _getShort(buf, offset + 4), 325 _getShort(buf, offset + 6)); 326 } else { 327 return makeLong(buf[offset], 328 buf[offset + 1], 329 buf[offset + 2], 330 buf[offset + 3], 331 buf[offset + 4], 332 buf[offset + 5], 333 buf[offset + 6], 334 buf[offset + 7]); 335 } 336 } 337 338 /** 339 * As {@link #getLongUnaligned(Object, long)} but with an 340 * additional argument which specifies the endianness of the value 341 * as stored in memory. 342 * 343 * @param o heap object in which the variable resides 344 * @param offset The offset in bytes from the start of the object 345 * @param bigEndian The endianness of the value 346 * @return the value fetched from the indicated object 347 */ 348 private static long getLongUnaligned(byte[] hb, size_t offset, bool bigEndian) { 349 return convEndian(bigEndian, getLongUnaligned(hb, offset)); 350 } 351 352 /** 353 * As {@link #putLongUnaligned(Object, long, long)} but with an additional 354 * argument which specifies the endianness of the value as stored in memory. 355 * @param o heap object in which the value resides 356 * @param offset The offset in bytes from the start of the object 357 * @param x the value to store 358 * @param bigEndian The endianness of the value 359 * @throws RuntimeException No defined exceptions are thrown, not even 360 * {@link NullPointerException} 361 */ 362 private static void putLongUnaligned(byte[] buf, size_t offset, long x, bool bigEndian) { 363 putLongUnaligned(buf, offset, convEndian(bigEndian, x)); 364 } 365 366 // These methods write integers to memory from smaller parts 367 // provided by their caller. The ordering in which these parts 368 // are written is the native endianness of this platform. 369 private static void putLongParts(byte[] buf, size_t offset, byte i0, byte i1, byte i2, 370 byte i3, byte i4, byte i5, byte i6, byte i7) { 371 buf[offset + 0] = pick(i0, i7); 372 buf[offset + 1] = pick(i1, i6); 373 buf[offset + 2] = pick(i2, i5); 374 buf[offset + 3] = pick(i3, i4); 375 buf[offset + 4] = pick(i4, i3); 376 buf[offset + 5] = pick(i5, i2); 377 buf[offset + 6] = pick(i6, i1); 378 buf[offset + 7] = pick(i7, i0); 379 } 380 381 private static void putLongParts(byte[] buf, size_t offset, short i0, short i1, short i2, short i3) { 382 _putShort(buf, offset + 0, pick(i0, i3)); 383 _putShort(buf, offset + 2, pick(i1, i2)); 384 _putShort(buf, offset + 4, pick(i2, i1)); 385 _putShort(buf, offset + 6, pick(i3, i0)); 386 } 387 388 private static void putLongParts(byte[] buf, size_t offset, int i0, int i1) { 389 _putInt(buf, offset + 0, pick(i0, i1)); 390 _putInt(buf, offset + 4, pick(i1, i0)); 391 } 392 393 private static void putLongUnaligned(byte[] hb, size_t offset, long x) { 394 if ((offset & 7) == 0) { 395 _putLong(hb, offset, x); 396 } else if ((offset & 3) == 0) { 397 putLongParts(hb, offset, 398 cast(int)(x >> 0), 399 cast(int)(x >>> 32)); 400 } else if ((offset & 1) == 0) { 401 putLongParts(hb, offset, 402 cast(short)(x >>> 0), 403 cast(short)(x >>> 16), 404 cast(short)(x >>> 32), 405 cast(short)(x >>> 48)); 406 } else { 407 putLongParts(hb, offset, 408 cast(byte)(x >>> 0), 409 cast(byte)(x >>> 8), 410 cast(byte)(x >>> 16), 411 cast(byte)(x >>> 24), 412 cast(byte)(x >>> 32), 413 cast(byte)(x >>> 40), 414 cast(byte)(x >>> 48), 415 cast(byte)(x >>> 56)); 416 } 417 } 418 419 private static short _getShort(byte[] buf, size_t offset) { 420 short* ptr = cast(short*)(buf.ptr + offset); 421 return *ptr; 422 } 423 424 private static void _putShort(byte[] buf, size_t offset, short x) { 425 buf[offset] = short0(x); 426 buf[offset + 1] = short1(x); 427 } 428 429 private static int _getInt(byte[] buf, size_t offset) { 430 int* ptr = cast(int*)(buf.ptr + offset); 431 return *ptr; 432 } 433 434 private static void _putInt(byte[] buf, size_t offset, int x) { 435 buf[offset] = int0(x); 436 buf[offset + 1] = int1(x); 437 buf[offset + 2] = int2(x); 438 buf[offset + 3] = int3(x); 439 } 440 441 private static long _getLong(byte[] buf, size_t offset) { 442 long* ptr = cast(long*)(buf.ptr + offset); 443 return *ptr; 444 } 445 446 private static void _putLong(byte[] buf, size_t offset, long x) { 447 buf[offset] = long0(x); 448 buf[offset + 1] = long1(x); 449 buf[offset + 2] = long2(x); 450 buf[offset + 3] = long3(x); 451 452 buf[offset + 4] = long4(x); 453 buf[offset + 5] = long5(x); 454 buf[offset + 6] = long6(x); 455 buf[offset + 7] = long7(x); 456 } 457 458 private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { 459 return ((toUnsignedLong(i0) << pickPos(56, 0)) 460 | (toUnsignedLong(i1) << pickPos(56, 8)) 461 | (toUnsignedLong(i2) << pickPos(56, 16)) 462 | (toUnsignedLong(i3) << pickPos(56, 24)) 463 | (toUnsignedLong(i4) << pickPos(56, 32)) 464 | (toUnsignedLong(i5) << pickPos(56, 40)) 465 | (toUnsignedLong(i6) << pickPos(56, 48)) 466 | (toUnsignedLong(i7) << pickPos(56, 56))); 467 } 468 469 private static long makeLong(short i0, short i1, short i2, short i3) { 470 return ((toUnsignedLong(i0) << pickPos(48, 0)) 471 | (toUnsignedLong(i1) << pickPos(48, 16)) 472 | (toUnsignedLong(i2) << pickPos(48, 32)) 473 | (toUnsignedLong(i3) << pickPos(48, 48))); 474 } 475 476 private static long makeLong(int i0, int i1) { 477 return (toUnsignedLong(i0) << pickPos(32, 0)) 478 | (toUnsignedLong(i1) << pickPos(32, 32)); 479 } 480 481 private static int makeInt(short i0, short i1) { 482 return (toUnsignedInt(i0) << pickPos(16, 0)) 483 | (toUnsignedInt(i1) << pickPos(16, 16)); 484 } 485 486 private static int makeInt(byte i0, byte i1, byte i2, byte i3) { 487 return ((toUnsignedInt(i0) << pickPos(24, 0)) 488 | (toUnsignedInt(i1) << pickPos(24, 8)) 489 | (toUnsignedInt(i2) << pickPos(24, 16)) 490 | (toUnsignedInt(i3) << pickPos(24, 24))); 491 } 492 493 static short makeShort(byte i0, byte i1) { 494 return cast(short)((toUnsignedInt(i0) << pickPos(8, 0)) 495 | (toUnsignedInt(i1) << pickPos(8, 8))); 496 } 497 498 private static short shortReverseBytes(short i) { 499 return cast(short) (((i & 0xFF00) >> 8) | (i << 8)); 500 } 501 502 private static int intReverseBytes(int i) { 503 return (i << 24) | 504 ((i & 0xff00) << 8) | 505 ((i >>> 8) & 0xff00) | 506 (i >>> 24); 507 } 508 509 private static long longReverseBytes(long i) { 510 i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; 511 return (i << 48) | ((i & 0xffff0000L) << 16) | 512 ((i >>> 16) & 0xffff0000L) | (i >>> 48); 513 } 514 515 version (LittleEndian) { 516 // Maybe byte-reverse an integer 517 // private static char convEndian(bool big, char n) { return big == BE ? n : Char.reverseBytes(n); } 518 private static short convEndian(bool big, short n) { return big ? shortReverseBytes(n) : n ; } 519 private static int convEndian(bool big, int n) { return big ? intReverseBytes(n) : n ; } 520 private static long convEndian(bool big, long n) { return big ? longReverseBytes(n) : n ; } 521 522 private static byte pick(byte le, byte be) { return le; } 523 private static short pick(short le, short be) { return le; } 524 private static int pick(int le, int be) { return le; } 525 526 private static int pickPos(int top, int pos) { return pos; } 527 } else { 528 // Maybe byte-reverse an integer 529 // private static char convEndian(bool big, char n) { return big == BE ? n : Character.reverseBytes(n); } 530 private static short convEndian(bool big, short n) { return big ? n : shortReverseBytes(n) ; } 531 private static int convEndian(bool big, int n) { return big ? n : intReverseBytes(n) ; } 532 private static long convEndian(bool big, long n) { return big ? n : longReverseBytes(n) ; } 533 534 private static byte pick(byte le, byte be) { return be; } 535 private static short pick(short le, short be) { return be; } 536 private static int pick(int le, int be) { return be; } 537 538 private static int pickPos(int top, int pos) { return top - pos; } 539 } 540 541 // Zero-extend an integer 542 private static int toUnsignedInt(byte n) { return n & 0xff; } 543 private static int toUnsignedInt(short n) { return n & 0xffff; } 544 private static long toUnsignedLong(byte n) { return n & 0xffL; } 545 private static long toUnsignedLong(short n) { return n & 0xffffL; } 546 private static long toUnsignedLong(int n) { return n & 0xffffffffL; } 547 548 // private static byte short1(short x) { return cast(byte)(x >> 8); } 549 // private static byte short0(short x) { return cast(byte)(x ); } 550 551 private static byte int3(int x) { return cast(byte)(x >> 24); } 552 private static byte int2(int x) { return cast(byte)(x >> 16); } 553 private static byte int1(int x) { return cast(byte)(x >> 8); } 554 private static byte int0(int x) { return cast(byte)(x ); } 555 556 private static byte long7(long x) { return cast(byte)(x >> 56); } 557 private static byte long6(long x) { return cast(byte)(x >> 48); } 558 private static byte long5(long x) { return cast(byte)(x >> 40); } 559 private static byte long4(long x) { return cast(byte)(x >> 32); } 560 private static byte long3(long x) { return cast(byte)(x >> 24); } 561 private static byte long2(long x) { return cast(byte)(x >> 16); } 562 private static byte long1(long x) { return cast(byte)(x >> 8); } 563 private static byte long0(long x) { return cast(byte)(x ); } 564 565 // dfmt on 566 567 override ByteBuffer compact() { 568 int sourceIndex = ix(position()); 569 int targetIndex = ix(0); 570 int len = remaining(); 571 // tracef("hb.length=%d, remaining=%d, targetIndex=%d, sourceIndex=%d", hb.length, len, targetIndex, sourceIndex) ; 572 if(targetIndex != sourceIndex) { 573 hb[targetIndex .. targetIndex + len] = hb[sourceIndex .. sourceIndex + len]; 574 position(len); 575 limit(capacity()); 576 discardMark(); 577 } 578 return this; 579 580 } 581 }