Slice是用于高效地处理堆和堆外内存一个Java 库
    Slice成员变量
    image.png
    详细介绍Slice类具体成员变量和具体实现方法

    1. /*
    2. * Licensed under the Apache License, Version 2.0 (the "License");
    3. * you may not use this file except in compliance with the License.
    4. * You may obtain a copy of the License at
    5. *
    6. * http://www.apache.org/licenses/LICENSE-2.0
    7. *
    8. * Unless required by applicable law or agreed to in writing, software
    9. * distributed under the License is distributed on an "AS IS" BASIS,
    10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11. * See the License for the specific language governing permissions and
    12. * limitations under the License.
    13. */
    14. package io.airlift.slice;
    15. import org.openjdk.jol.info.ClassLayout;
    16. import sun.misc.Unsafe;
    17. import javax.annotation.Nullable;
    18. import java.io.IOException;
    19. import java.io.InputStream;
    20. import java.io.OutputStream;
    21. import java.nio.ByteBuffer;
    22. import java.nio.charset.Charset;
    23. import static io.airlift.slice.JvmUtils.bufferAddress;
    24. import static io.airlift.slice.JvmUtils.unsafe;
    25. import static io.airlift.slice.Preconditions.checkArgument;
    26. import static io.airlift.slice.Preconditions.checkPositionIndexes;
    27. import static io.airlift.slice.SizeOf.SIZE_OF_BYTE;
    28. import static io.airlift.slice.SizeOf.SIZE_OF_DOUBLE;
    29. import static io.airlift.slice.SizeOf.SIZE_OF_FLOAT;
    30. import static io.airlift.slice.SizeOf.SIZE_OF_INT;
    31. import static io.airlift.slice.SizeOf.SIZE_OF_LONG;
    32. import static io.airlift.slice.SizeOf.SIZE_OF_SHORT;
    33. import static io.airlift.slice.SizeOf.sizeOf;
    34. import static io.airlift.slice.SizeOf.sizeOfBooleanArray;
    35. import static io.airlift.slice.SizeOf.sizeOfDoubleArray;
    36. import static io.airlift.slice.SizeOf.sizeOfFloatArray;
    37. import static io.airlift.slice.SizeOf.sizeOfIntArray;
    38. import static io.airlift.slice.SizeOf.sizeOfLongArray;
    39. import static io.airlift.slice.SizeOf.sizeOfShortArray;
    40. import static java.lang.Math.min;
    41. import static java.lang.Math.multiplyExact;
    42. import static java.lang.Math.toIntExact;
    43. import static java.lang.String.format;
    44. import static java.nio.charset.StandardCharsets.UTF_8;
    45. import static java.util.Objects.requireNonNull;
    46. import static sun.misc.Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
    47. import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
    48. import static sun.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
    49. import static sun.misc.Unsafe.ARRAY_FLOAT_INDEX_SCALE;
    50. import static sun.misc.Unsafe.ARRAY_INT_INDEX_SCALE;
    51. import static sun.misc.Unsafe.ARRAY_LONG_INDEX_SCALE;
    52. import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE;
    53. public final class Slice
    54. implements Comparable<Slice>
    55. {
    56. private static final int INSTANCE_SIZE = ClassLayout.parseClass(Slice.class).instanceSize();
    57. private static final Object COMPACT = new byte[0];
    58. private static final Object NOT_COMPACT = null;
    59. private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
    60. /**
    61. * Base object for relative addresses. If null, the address is an
    62. * absolute location in memory.
    63. */
    64. private final Object base;
    65. /**
    66. * If base is null, address is the absolute memory location of data for
    67. * this slice; otherwise, address is the offset from the base object.
    68. * This base plus relative offset addressing is taken directly from
    69. * the Unsafe interface.
    70. * <p>
    71. * Note: if base object is a byte array, this address ARRAY_BYTE_BASE_OFFSET,
    72. * since the byte array data starts AFTER the byte array object header.
    73. */
    74. private final long address;
    75. /**
    76. * Size of the slice
    77. */
    78. private final int size;
    79. /**
    80. * Bytes retained by the slice
    81. */
    82. private final long retainedSize;
    83. /**
    84. * Reference has two use cases:
    85. * <p>
    86. * 1. It can be an object this slice must hold onto to assure that the
    87. * underlying memory is not freed by the garbage collector.
    88. * It is typically a ByteBuffer object, but can be any object.
    89. * This is not needed for arrays, since the array is referenced by {@code base}.
    90. * <p>
    91. * 2. If reference is not used to prevent garbage collector from freeing the
    92. * underlying memory, it will be used to indicate if the slice is compact.
    93. * When {@code reference == COMPACT}, the slice is considered as compact.
    94. * Otherwise, it will be null.
    95. * <p>
    96. * A slice is considered compact if the base object is an heap array and
    97. * it contains the whole array.
    98. * Thus, for the first use case, the slice is always considered as not compact.
    99. */
    100. private final Object reference;
    101. private int hash;
    102. /**
    103. * Creates an empty slice.
    104. */
    105. Slice()
    106. {
    107. this.base = null;
    108. this.address = 0;
    109. this.size = 0;
    110. this.retainedSize = INSTANCE_SIZE;
    111. this.reference = COMPACT;
    112. }
    113. /**
    114. * Creates a slice over the specified array.
    115. */
    116. Slice(byte[] base)
    117. {
    118. requireNonNull(base, "base is null");
    119. this.base = base;
    120. this.address = ARRAY_BYTE_BASE_OFFSET;
    121. this.size = base.length;
    122. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    123. this.reference = COMPACT;
    124. }
    125. /**
    126. * Creates a slice over the specified array range.
    127. *
    128. * @param offset the array position at which the slice begins
    129. * @param length the number of array positions to include in the slice
    130. */
    131. Slice(byte[] base, int offset, int length)
    132. {
    133. requireNonNull(base, "base is null");
    134. checkPositionIndexes(offset, offset + length, base.length);
    135. this.base = base;
    136. this.address = ARRAY_BYTE_BASE_OFFSET + offset;
    137. this.size = length;
    138. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    139. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    140. }
    141. /**
    142. * Creates a slice over the specified array range.
    143. *
    144. * @param offset the array position at which the slice begins
    145. * @param length the number of array positions to include in the slice
    146. */
    147. Slice(boolean[] base, int offset, int length)
    148. {
    149. requireNonNull(base, "base is null");
    150. checkPositionIndexes(offset, offset + length, base.length);
    151. this.base = base;
    152. this.address = sizeOfBooleanArray(offset);
    153. this.size = multiplyExact(length, ARRAY_BOOLEAN_INDEX_SCALE);
    154. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    155. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    156. }
    157. /**
    158. * Creates a slice over the specified array range.
    159. *
    160. * @param offset the array position at which the slice begins
    161. * @param length the number of array positions to include in the slice
    162. */
    163. Slice(short[] base, int offset, int length)
    164. {
    165. requireNonNull(base, "base is null");
    166. checkPositionIndexes(offset, offset + length, base.length);
    167. this.base = base;
    168. this.address = sizeOfShortArray(offset);
    169. this.size = multiplyExact(length, ARRAY_SHORT_INDEX_SCALE);
    170. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    171. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    172. }
    173. /**
    174. * Creates a slice over the specified array range.
    175. *
    176. * @param offset the array position at which the slice begins
    177. * @param length the number of array positions to include in the slice
    178. */
    179. Slice(int[] base, int offset, int length)
    180. {
    181. requireNonNull(base, "base is null");
    182. checkPositionIndexes(offset, offset + length, base.length);
    183. this.base = base;
    184. this.address = sizeOfIntArray(offset);
    185. this.size = multiplyExact(length, ARRAY_INT_INDEX_SCALE);
    186. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    187. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    188. }
    189. /**
    190. * Creates a slice over the specified array range.
    191. *
    192. * @param offset the array position at which the slice begins
    193. * @param length the number of array positions to include in the slice
    194. */
    195. Slice(long[] base, int offset, int length)
    196. {
    197. requireNonNull(base, "base is null");
    198. checkPositionIndexes(offset, offset + length, base.length);
    199. this.base = base;
    200. this.address = sizeOfLongArray(offset);
    201. this.size = multiplyExact(length, ARRAY_LONG_INDEX_SCALE);
    202. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    203. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    204. }
    205. /**
    206. * Creates a slice over the specified array range.
    207. *
    208. * @param offset the array position at which the slice begins
    209. * @param length the number of array positions to include in the slice
    210. */
    211. Slice(float[] base, int offset, int length)
    212. {
    213. requireNonNull(base, "base is null");
    214. checkPositionIndexes(offset, offset + length, base.length);
    215. this.base = base;
    216. this.address = sizeOfFloatArray(offset);
    217. this.size = multiplyExact(length, ARRAY_FLOAT_INDEX_SCALE);
    218. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    219. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    220. }
    221. /**
    222. * Creates a slice over the specified array range.
    223. *
    224. * @param offset the array position at which the slice begins
    225. * @param length the number of array positions to include in the slice
    226. */
    227. Slice(double[] base, int offset, int length)
    228. {
    229. requireNonNull(base, "base is null");
    230. checkPositionIndexes(offset, offset + length, base.length);
    231. this.base = base;
    232. this.address = sizeOfDoubleArray(offset);
    233. this.size = multiplyExact(length, ARRAY_DOUBLE_INDEX_SCALE);
    234. this.retainedSize = INSTANCE_SIZE + sizeOf(base);
    235. this.reference = (offset == 0 && length == base.length) ? COMPACT : NOT_COMPACT;
    236. }
    237. /**
    238. * Creates a slice for directly accessing the base object.
    239. */
    240. Slice(@Nullable Object base, long address, int size, long retainedSize, @Nullable Object reference)
    241. {
    242. if (address <= 0) {
    243. throw new IllegalArgumentException(format("Invalid address: %s", address));
    244. }
    245. if (size <= 0) {
    246. throw new IllegalArgumentException(format("Invalid size: %s", size));
    247. }
    248. checkArgument((address + size) >= size, "Address + size is greater than 64 bits");
    249. this.reference = reference;
    250. this.base = base;
    251. this.address = address;
    252. this.size = size;
    253. // INSTANCE_SIZE is not included, as the caller is responsible for including it.
    254. this.retainedSize = retainedSize;
    255. }
    256. /**
    257. * Returns the base object of this Slice, or null. This is appropriate for use
    258. * with {@link Unsafe} if you wish to avoid all the safety belts e.g. bounds checks.
    259. */
    260. public Object getBase()
    261. {
    262. return base;
    263. }
    264. /**
    265. * Return the address offset of this Slice. This is appropriate for use
    266. * with {@link Unsafe} if you wish to avoid all the safety belts e.g. bounds checks.
    267. */
    268. public long getAddress()
    269. {
    270. return address;
    271. }
    272. /**
    273. * Length of this slice.
    274. */
    275. public int length()
    276. {
    277. return size;
    278. }
    279. /**
    280. * Approximate number of bytes retained by this slice.
    281. */
    282. public long getRetainedSize()
    283. {
    284. return retainedSize;
    285. }
    286. /**
    287. * A slice is considered compact if the base object is an array and it contains the whole array.
    288. * As a result, it cannot be a view of a bigger slice.
    289. */
    290. public boolean isCompact()
    291. {
    292. return reference == COMPACT;
    293. }
    294. private void checkHasByteArray()
    295. throws UnsupportedOperationException
    296. {
    297. if (!hasByteArray()) {
    298. throw new UnsupportedOperationException("Slice is not backed by a byte array");
    299. }
    300. }
    301. public boolean hasByteArray()
    302. {
    303. return base instanceof byte[];
    304. }
    305. /**
    306. * Returns the byte array wrapped by this Slice, if any. Callers are expected to check {@link Slice#hasByteArray()} before calling
    307. * this method since not all instances are backed by a byte array. Callers should also take care to use {@link Slice#byteArrayOffset()}
    308. * since the contents of this Slice may not start at array index 0.
    309. *
    310. * @throws UnsupportedOperationException if this Slice has no underlying byte array
    311. */
    312. public byte[] byteArray()
    313. throws UnsupportedOperationException
    314. {
    315. checkHasByteArray();
    316. return (byte[]) base;
    317. }
    318. /**
    319. * Returns the start index the content of this slice within the byte array wrapped by this slice. Callers should
    320. * check {@link Slice#hasByteArray()} before calling this method since not all Slices wrap a heap byte array
    321. *
    322. * @throws UnsupportedOperationException if this Slice has no underlying byte array
    323. */
    324. public int byteArrayOffset()
    325. throws UnsupportedOperationException
    326. {
    327. checkHasByteArray();
    328. return (int) (address - ARRAY_BYTE_BASE_OFFSET);
    329. }
    330. /**
    331. * Fill the slice with the specified value;
    332. */
    333. public void fill(byte value)
    334. {
    335. int offset = 0;
    336. int length = size;
    337. long longValue = fillLong(value);
    338. while (length >= SIZE_OF_LONG) {
    339. unsafe.putLong(base, address + offset, longValue);
    340. offset += SIZE_OF_LONG;
    341. length -= SIZE_OF_LONG;
    342. }
    343. while (length > 0) {
    344. unsafe.putByte(base, address + offset, value);
    345. offset++;
    346. length--;
    347. }
    348. }
    349. /**
    350. * Fill the slice with zeros;
    351. */
    352. public void clear()
    353. {
    354. clear(0, size);
    355. }
    356. public void clear(int offset, int length)
    357. {
    358. while (length >= SIZE_OF_LONG) {
    359. unsafe.putLong(base, address + offset, 0);
    360. offset += SIZE_OF_LONG;
    361. length -= SIZE_OF_LONG;
    362. }
    363. while (length > 0) {
    364. unsafe.putByte(base, address + offset, (byte) 0);
    365. offset++;
    366. length--;
    367. }
    368. }
    369. /**
    370. * Gets a byte at the specified absolute {@code index} in this buffer.
    371. *
    372. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    373. * {@code index + 1} is greater than {@code this.length()}
    374. */
    375. public byte getByte(int index)
    376. {
    377. checkIndexLength(index, SIZE_OF_BYTE);
    378. return getByteUnchecked(index);
    379. }
    380. byte getByteUnchecked(int index)
    381. {
    382. return unsafe.getByte(base, address + index);
    383. }
    384. /**
    385. * Gets an unsigned byte at the specified absolute {@code index} in this
    386. * buffer.
    387. *
    388. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    389. * {@code index + 1} is greater than {@code this.length()}
    390. */
    391. public short getUnsignedByte(int index)
    392. {
    393. return (short) (getByte(index) & 0xFF);
    394. }
    395. /**
    396. * Gets a 16-bit short integer at the specified absolute {@code index} in
    397. * this slice.
    398. *
    399. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    400. * {@code index + 2} is greater than {@code this.length()}
    401. */
    402. public short getShort(int index)
    403. {
    404. checkIndexLength(index, SIZE_OF_SHORT);
    405. return getShortUnchecked(index);
    406. }
    407. short getShortUnchecked(int index)
    408. {
    409. return unsafe.getShort(base, address + index);
    410. }
    411. /**
    412. * Gets an unsigned 16-bit short integer at the specified absolute {@code index}
    413. * in this slice.
    414. *
    415. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    416. * {@code index + 2} is greater than {@code this.length()}
    417. */
    418. public int getUnsignedShort(int index)
    419. {
    420. return getShort(index) & 0xFFFF;
    421. }
    422. /**
    423. * Gets a 32-bit integer at the specified absolute {@code index} in
    424. * this buffer.
    425. *
    426. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    427. * {@code index + 4} is greater than {@code this.length()}
    428. */
    429. public int getInt(int index)
    430. {
    431. checkIndexLength(index, SIZE_OF_INT);
    432. return getIntUnchecked(index);
    433. }
    434. int getIntUnchecked(int index)
    435. {
    436. return unsafe.getInt(base, address + index);
    437. }
    438. /**
    439. * Gets an unsigned 32-bit integer at the specified absolute {@code index} in
    440. * this buffer.
    441. *
    442. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    443. * {@code index + 4} is greater than {@code this.length()}
    444. */
    445. public long getUnsignedInt(int index)
    446. {
    447. return getInt(index) & 0xFFFFFFFFL;
    448. }
    449. /**
    450. * Gets a 64-bit long integer at the specified absolute {@code index} in
    451. * this buffer.
    452. *
    453. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    454. * {@code index + 8} is greater than {@code this.length()}
    455. */
    456. public long getLong(int index)
    457. {
    458. checkIndexLength(index, SIZE_OF_LONG);
    459. return getLongUnchecked(index);
    460. }
    461. long getLongUnchecked(int index)
    462. {
    463. return unsafe.getLong(base, address + index);
    464. }
    465. /**
    466. * Gets a 32-bit float at the specified absolute {@code index} in
    467. * this buffer.
    468. *
    469. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    470. * {@code index + 4} is greater than {@code this.length()}
    471. */
    472. public float getFloat(int index)
    473. {
    474. checkIndexLength(index, SIZE_OF_FLOAT);
    475. return unsafe.getFloat(base, address + index);
    476. }
    477. /**
    478. * Gets a 64-bit double at the specified absolute {@code index} in
    479. * this buffer.
    480. *
    481. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    482. * {@code index + 8} is greater than {@code this.length()}
    483. */
    484. public double getDouble(int index)
    485. {
    486. checkIndexLength(index, SIZE_OF_DOUBLE);
    487. return unsafe.getDouble(base, address + index);
    488. }
    489. /**
    490. * Transfers portion of data from this slice into the specified destination starting at
    491. * the specified absolute {@code index}.
    492. *
    493. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, or
    494. * if {@code index + destination.length()} is greater than {@code this.length()}
    495. */
    496. public void getBytes(int index, Slice destination)
    497. {
    498. getBytes(index, destination, 0, destination.length());
    499. }
    500. /**
    501. * Transfers portion of data from this slice into the specified destination starting at
    502. * the specified absolute {@code index}.
    503. *
    504. * @param destinationIndex the first index of the destination
    505. * @param length the number of bytes to transfer
    506. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0},
    507. * if the specified {@code destinationIndex} is less than {@code 0},
    508. * if {@code index + length} is greater than
    509. * {@code this.length()}, or
    510. * if {@code destinationIndex + length} is greater than
    511. * {@code destination.length()}
    512. */
    513. public void getBytes(int index, Slice destination, int destinationIndex, int length)
    514. {
    515. destination.setBytes(destinationIndex, this, index, length);
    516. }
    517. /**
    518. * Transfers portion of data from this slice into the specified destination starting at
    519. * the specified absolute {@code index}.
    520. *
    521. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, or
    522. * if {@code index + destination.length} is greater than {@code this.length()}
    523. */
    524. public void getBytes(int index, byte[] destination)
    525. {
    526. getBytes(index, destination, 0, destination.length);
    527. }
    528. /**
    529. * Transfers portion of data from this slice into the specified destination starting at
    530. * the specified absolute {@code index}.
    531. *
    532. * @param destinationIndex the first index of the destination
    533. * @param length the number of bytes to transfer
    534. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0},
    535. * if the specified {@code destinationIndex} is less than {@code 0},
    536. * if {@code index + length} is greater than
    537. * {@code this.length()}, or
    538. * if {@code destinationIndex + length} is greater than
    539. * {@code destination.length}
    540. */
    541. public void getBytes(int index, byte[] destination, int destinationIndex, int length)
    542. {
    543. checkIndexLength(index, length);
    544. checkPositionIndexes(destinationIndex, destinationIndex + length, destination.length);
    545. copyMemory(base, address + index, destination, (long) ARRAY_BYTE_BASE_OFFSET + destinationIndex, length);
    546. }
    547. /**
    548. * Returns a copy of this buffer as a byte array.
    549. */
    550. public byte[] getBytes()
    551. {
    552. return getBytes(0, length());
    553. }
    554. /**
    555. * Returns a copy of this buffer as a byte array.
    556. *
    557. * @param index the absolute index to start at
    558. * @param length the number of bytes to return
    559. * @throws IndexOutOfBoundsException if the specified {@code index} is less then {@code 0},
    560. * or if the specified {@code index + length} is greater than {@code this.length()}
    561. */
    562. public byte[] getBytes(int index, int length)
    563. {
    564. byte[] bytes = new byte[length];
    565. getBytes(index, bytes, 0, length);
    566. return bytes;
    567. }
    568. /**
    569. * Transfers a portion of data from this slice into the specified stream starting at the
    570. * specified absolute {@code index}.
    571. *
    572. * @param length the number of bytes to transfer
    573. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    574. * if {@code index + length} is greater than
    575. * {@code this.length()}
    576. * @throws java.io.IOException if the specified stream threw an exception during I/O
    577. */
    578. public void getBytes(int index, OutputStream out, int length)
    579. throws IOException
    580. {
    581. checkIndexLength(index, length);
    582. if (hasByteArray()) {
    583. out.write(byteArray(), byteArrayOffset() + index, length);
    584. return;
    585. }
    586. byte[] buffer = new byte[4096];
    587. while (length > 0) {
    588. int size = min(buffer.length, length);
    589. getBytes(index, buffer, 0, size);
    590. out.write(buffer, 0, size);
    591. length -= size;
    592. index += size;
    593. }
    594. }
    595. /**
    596. * Sets the specified byte at the specified absolute {@code index} in this
    597. * buffer. The 24 high-order bits of the specified value are ignored.
    598. *
    599. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    600. * {@code index + 1} is greater than {@code this.length()}
    601. */
    602. public void setByte(int index, int value)
    603. {
    604. checkIndexLength(index, SIZE_OF_BYTE);
    605. setByteUnchecked(index, value);
    606. }
    607. void setByteUnchecked(int index, int value)
    608. {
    609. unsafe.putByte(base, address + index, (byte) (value & 0xFF));
    610. }
    611. /**
    612. * Sets the specified 16-bit short integer at the specified absolute
    613. * {@code index} in this buffer. The 16 high-order bits of the specified
    614. * value are ignored.
    615. *
    616. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    617. * {@code index + 2} is greater than {@code this.length()}
    618. */
    619. public void setShort(int index, int value)
    620. {
    621. checkIndexLength(index, SIZE_OF_SHORT);
    622. setShortUnchecked(index, value);
    623. }
    624. void setShortUnchecked(int index, int value)
    625. {
    626. unsafe.putShort(base, address + index, (short) (value & 0xFFFF));
    627. }
    628. /**
    629. * Sets the specified 32-bit integer at the specified absolute
    630. * {@code index} in this buffer.
    631. *
    632. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    633. * {@code index + 4} is greater than {@code this.length()}
    634. */
    635. public void setInt(int index, int value)
    636. {
    637. checkIndexLength(index, SIZE_OF_INT);
    638. setIntUnchecked(index, value);
    639. }
    640. void setIntUnchecked(int index, int value)
    641. {
    642. unsafe.putInt(base, address + index, value);
    643. }
    644. /**
    645. * Sets the specified 64-bit long integer at the specified absolute
    646. * {@code index} in this buffer.
    647. *
    648. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    649. * {@code index + 8} is greater than {@code this.length()}
    650. */
    651. public void setLong(int index, long value)
    652. {
    653. checkIndexLength(index, SIZE_OF_LONG);
    654. setLongUnchecked(index, value);
    655. }
    656. void setLongUnchecked(int index, long value)
    657. {
    658. unsafe.putLong(base, address + index, value);
    659. }
    660. /**
    661. * Sets the specified 32-bit float at the specified absolute
    662. * {@code index} in this buffer.
    663. *
    664. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    665. * {@code index + 4} is greater than {@code this.length()}
    666. */
    667. public void setFloat(int index, float value)
    668. {
    669. checkIndexLength(index, SIZE_OF_FLOAT);
    670. unsafe.putFloat(base, address + index, value);
    671. }
    672. /**
    673. * Sets the specified 64-bit double at the specified absolute
    674. * {@code index} in this buffer.
    675. *
    676. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0} or
    677. * {@code index + 8} is greater than {@code this.length()}
    678. */
    679. public void setDouble(int index, double value)
    680. {
    681. checkIndexLength(index, SIZE_OF_DOUBLE);
    682. unsafe.putDouble(base, address + index, value);
    683. }
    684. /**
    685. * Transfers data from the specified slice into this buffer starting at
    686. * the specified absolute {@code index}.
    687. *
    688. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, or
    689. * if {@code index + source.length()} is greater than {@code this.length()}
    690. */
    691. public void setBytes(int index, Slice source)
    692. {
    693. setBytes(index, source, 0, source.length());
    694. }
    695. /**
    696. * Transfers data from the specified slice into this buffer starting at
    697. * the specified absolute {@code index}.
    698. *
    699. * @param sourceIndex the first index of the source
    700. * @param length the number of bytes to transfer
    701. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0},
    702. * if the specified {@code sourceIndex} is less than {@code 0},
    703. * if {@code index + length} is greater than
    704. * {@code this.length()}, or
    705. * if {@code sourceIndex + length} is greater than
    706. * {@code source.length()}
    707. */
    708. public void setBytes(int index, Slice source, int sourceIndex, int length)
    709. {
    710. checkIndexLength(index, length);
    711. checkPositionIndexes(sourceIndex, sourceIndex + length, source.length());
    712. copyMemory(source.base, source.address + sourceIndex, base, address + index, length);
    713. }
    714. /**
    715. * Transfers data from the specified slice into this buffer starting at
    716. * the specified absolute {@code index}.
    717. *
    718. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, or
    719. * if {@code index + source.length} is greater than {@code this.length()}
    720. */
    721. public void setBytes(int index, byte[] source)
    722. {
    723. setBytes(index, source, 0, source.length);
    724. }
    725. /**
    726. * Transfers data from the specified array into this buffer starting at
    727. * the specified absolute {@code index}.
    728. *
    729. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0},
    730. * if the specified {@code sourceIndex} is less than {@code 0},
    731. * if {@code index + length} is greater than
    732. * {@code this.length()}, or
    733. * if {@code sourceIndex + length} is greater than {@code source.length}
    734. */
    735. public void setBytes(int index, byte[] source, int sourceIndex, int length)
    736. {
    737. checkIndexLength(index, length);
    738. checkPositionIndexes(sourceIndex, sourceIndex + length, source.length);
    739. copyMemory(source, (long) ARRAY_BYTE_BASE_OFFSET + sourceIndex, base, address + index, length);
    740. }
    741. /**
    742. * Transfers data from the specified input stream into this slice starting at
    743. * the specified absolute {@code index}.
    744. *
    745. * @throws IndexOutOfBoundsException if the specified {@code index} is less than {@code 0}, or
    746. * if {@code index + source.length} is greater than {@code this.length()}
    747. */
    748. public void setBytes(int index, InputStream in, int length)
    749. throws IOException
    750. {
    751. checkIndexLength(index, length);
    752. if (hasByteArray()) {
    753. byte[] bytes = byteArray();
    754. int offset = byteArrayOffset() + index;
    755. while (length > 0) {
    756. int bytesRead = in.read(bytes, offset, length);
    757. if (bytesRead < 0) {
    758. throw new IndexOutOfBoundsException("End of stream");
    759. }
    760. length -= bytesRead;
    761. offset += bytesRead;
    762. }
    763. return;
    764. }
    765. byte[] bytes = new byte[4096];
    766. while (length > 0) {
    767. int bytesRead = in.read(bytes, 0, min(bytes.length, length));
    768. if (bytesRead < 0) {
    769. throw new IndexOutOfBoundsException("End of stream");
    770. }
    771. copyMemory(bytes, ARRAY_BYTE_BASE_OFFSET, base, address + index, bytesRead);
    772. length -= bytesRead;
    773. index += bytesRead;
    774. }
    775. }
    776. /**
    777. * Returns a slice of this buffer's sub-region. Modifying the content of
    778. * the returned buffer or this buffer affects each other's content.
    779. */
    780. public Slice slice(int index, int length)
    781. {
    782. if ((index == 0) && (length == length())) {
    783. return this;
    784. }
    785. checkIndexLength(index, length);
    786. if (length == 0) {
    787. return Slices.EMPTY_SLICE;
    788. }
    789. if (reference == COMPACT) {
    790. return new Slice(base, address + index, length, retainedSize, NOT_COMPACT);
    791. }
    792. return new Slice(base, address + index, length, retainedSize, reference);
    793. }
    794. public int indexOfByte(int b)
    795. {
    796. checkArgument((b >> Byte.SIZE) == 0, "byte value out of range");
    797. return indexOfByte((byte) b);
    798. }
    799. public int indexOfByte(byte b)
    800. {
    801. for (int i = 0; i < size; i++) {
    802. if (getByteUnchecked(i) == b) {
    803. return i;
    804. }
    805. }
    806. return -1;
    807. }
    808. /**
    809. * Returns the index of the first occurrence of the pattern with this slice.
    810. * If the pattern is not found -1 is returned. If patten is empty, zero is
    811. * returned.
    812. */
    813. public int indexOf(Slice slice)
    814. {
    815. return indexOf(slice, 0);
    816. }
    817. /**
    818. * Returns the index of the first occurrence of the pattern with this slice.
    819. * If the pattern is not found -1 is returned. If patten is empty, the offset
    820. * is returned.
    821. */
    822. public int indexOf(Slice pattern, int offset)
    823. {
    824. if (size == 0 || offset >= size) {
    825. return -1;
    826. }
    827. if (pattern.length() == 0) {
    828. return offset;
    829. }
    830. // Do we have enough characters
    831. if (pattern.length() < SIZE_OF_INT || size < SIZE_OF_LONG) {
    832. return indexOfBruteForce(pattern, offset);
    833. }
    834. // Using first four bytes for faster search. We are not using eight bytes for long
    835. // because we want more strings to get use of fast search.
    836. int head = pattern.getIntUnchecked(0);
    837. // Take the first byte of head for faster skipping
    838. int firstByteMask = head & 0xff;
    839. firstByteMask |= firstByteMask << 8;
    840. firstByteMask |= firstByteMask << 16;
    841. int lastValidIndex = size - pattern.length();
    842. int index = offset;
    843. while (index <= lastValidIndex) {
    844. // Read four bytes in sequence
    845. int value = getIntUnchecked(index);
    846. // Compare all bytes of value with first byte of search data
    847. // see https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
    848. int valueXor = value ^ firstByteMask;
    849. int hasZeroBytes = (valueXor - 0x01010101) & ~valueXor & 0x80808080;
    850. // If valueXor doesn't have any zero byte then there is no match and we can advance
    851. if (hasZeroBytes == 0) {
    852. index += SIZE_OF_INT;
    853. continue;
    854. }
    855. // Try fast match of head and the rest
    856. if (value == head && equalsUnchecked(index, pattern, 0, pattern.length())) {
    857. return index;
    858. }
    859. index++;
    860. }
    861. return -1;
    862. }
    863. int indexOfBruteForce(Slice pattern, int offset)
    864. {
    865. if (size == 0 || offset >= size) {
    866. return -1;
    867. }
    868. if (pattern.length() == 0) {
    869. return offset;
    870. }
    871. byte firstByte = pattern.getByteUnchecked(0);
    872. int lastValidIndex = size - pattern.length();
    873. int index = offset;
    874. while (true) {
    875. // seek to first byte match
    876. while (index < lastValidIndex && getByteUnchecked(index) != firstByte) {
    877. index++;
    878. }
    879. if (index > lastValidIndex) {
    880. break;
    881. }
    882. if (equalsUnchecked(index, pattern, 0, pattern.length())) {
    883. return index;
    884. }
    885. index++;
    886. }
    887. return -1;
    888. }
    889. /**
    890. * Compares the content of the specified buffer to the content of this
    891. * buffer. This comparison is performed byte by byte using an unsigned
    892. * comparison.
    893. */
    894. @SuppressWarnings("ObjectEquality")
    895. @Override
    896. public int compareTo(Slice that)
    897. {
    898. if (this == that) {
    899. return 0;
    900. }
    901. return compareTo(0, size, that, 0, that.size);
    902. }
    903. /**
    904. * Compares a portion of this slice with a portion of the specified slice. Equality is
    905. * solely based on the contents of the slice.
    906. */
    907. @SuppressWarnings("ObjectEquality")
    908. public int compareTo(int offset, int length, Slice that, int otherOffset, int otherLength)
    909. {
    910. if ((this == that) && (offset == otherOffset) && (length == otherLength)) {
    911. return 0;
    912. }
    913. checkIndexLength(offset, length);
    914. that.checkIndexLength(otherOffset, otherLength);
    915. long thisAddress = address + offset;
    916. long thatAddress = that.address + otherOffset;
    917. int compareLength = min(length, otherLength);
    918. while (compareLength >= SIZE_OF_LONG) {
    919. long thisLong = unsafe.getLong(base, thisAddress);
    920. long thatLong = unsafe.getLong(that.base, thatAddress);
    921. if (thisLong != thatLong) {
    922. return longBytesToLong(thisLong) < longBytesToLong(thatLong) ? -1 : 1;
    923. }
    924. thisAddress += SIZE_OF_LONG;
    925. thatAddress += SIZE_OF_LONG;
    926. compareLength -= SIZE_OF_LONG;
    927. }
    928. while (compareLength > 0) {
    929. byte thisByte = unsafe.getByte(base, thisAddress);
    930. byte thatByte = unsafe.getByte(that.base, thatAddress);
    931. int v = compareUnsignedBytes(thisByte, thatByte);
    932. if (v != 0) {
    933. return v;
    934. }
    935. thisAddress++;
    936. thatAddress++;
    937. compareLength--;
    938. }
    939. return Integer.compare(length, otherLength);
    940. }
    941. /**
    942. * Compares the specified object with this slice for equality. Equality is
    943. * solely based on the contents of the slice.
    944. */
    945. @Override
    946. public boolean equals(Object o)
    947. {
    948. if (this == o) {
    949. return true;
    950. }
    951. if (!(o instanceof Slice)) {
    952. return false;
    953. }
    954. Slice that = (Slice) o;
    955. if (length() != that.length()) {
    956. return false;
    957. }
    958. return equalsUnchecked(0, that, 0, length());
    959. }
    960. /**
    961. * Returns the hash code of this slice. The hash code is cached once calculated
    962. * and any future changes to the slice will not effect the hash code.
    963. */
    964. @SuppressWarnings("NonFinalFieldReferencedInHashCode")
    965. @Override
    966. public int hashCode()
    967. {
    968. if (hash != 0) {
    969. return hash;
    970. }
    971. hash = hashCode(0, size);
    972. return hash;
    973. }
    974. /**
    975. * Returns the hash code of a portion of this slice.
    976. */
    977. public int hashCode(int offset, int length)
    978. {
    979. return (int) XxHash64.hash(this, offset, length);
    980. }
    981. /**
    982. * Compares a portion of this slice with a portion of the specified slice. Equality is
    983. * solely based on the contents of the slice.
    984. */
    985. @SuppressWarnings("ObjectEquality")
    986. public boolean equals(int offset, int length, Slice that, int otherOffset, int otherLength)
    987. {
    988. if (length != otherLength) {
    989. return false;
    990. }
    991. if ((this == that) && (offset == otherOffset)) {
    992. return true;
    993. }
    994. checkIndexLength(offset, length);
    995. that.checkIndexLength(otherOffset, otherLength);
    996. return equalsUnchecked(offset, that, otherOffset, length);
    997. }
    998. boolean equalsUnchecked(int offset, Slice that, int otherOffset, int length)
    999. {
    1000. long thisAddress = address + offset;
    1001. long thatAddress = that.address + otherOffset;
    1002. while (length >= SIZE_OF_LONG) {
    1003. long thisLong = unsafe.getLong(base, thisAddress);
    1004. long thatLong = unsafe.getLong(that.base, thatAddress);
    1005. if (thisLong != thatLong) {
    1006. return false;
    1007. }
    1008. thisAddress += SIZE_OF_LONG;
    1009. thatAddress += SIZE_OF_LONG;
    1010. length -= SIZE_OF_LONG;
    1011. }
    1012. while (length > 0) {
    1013. byte thisByte = unsafe.getByte(base, thisAddress);
    1014. byte thatByte = unsafe.getByte(that.base, thatAddress);
    1015. if (thisByte != thatByte) {
    1016. return false;
    1017. }
    1018. thisAddress++;
    1019. thatAddress++;
    1020. length--;
    1021. }
    1022. return true;
    1023. }
    1024. /**
    1025. * Creates a slice input backed by this slice. Any changes to this slice
    1026. * will be immediately visible to the slice input.
    1027. */
    1028. public BasicSliceInput getInput()
    1029. {
    1030. return new BasicSliceInput(this);
    1031. }
    1032. /**
    1033. * Creates a slice output backed by this slice. Any data written to the
    1034. * slice output will be immediately visible in this slice.
    1035. */
    1036. public SliceOutput getOutput()
    1037. {
    1038. return new BasicSliceOutput(this);
    1039. }
    1040. /**
    1041. * Decodes the contents of this slice into a string with the specified
    1042. * character set name.
    1043. */
    1044. public String toString(Charset charset)
    1045. {
    1046. return toString(0, length(), charset);
    1047. }
    1048. /**
    1049. * Decodes the contents of this slice into a string using the UTF-8
    1050. * character set.
    1051. */
    1052. public String toStringUtf8()
    1053. {
    1054. return toString(UTF_8);
    1055. }
    1056. /**
    1057. * Decodes the contents of this slice into a string using the US_ASCII
    1058. * character set. The low order 7 bits if each byte are converted directly
    1059. * into a code point for the string.
    1060. */
    1061. public String toStringAscii()
    1062. {
    1063. return toStringAscii(0, size);
    1064. }
    1065. public String toStringAscii(int index, int length)
    1066. {
    1067. checkIndexLength(index, length);
    1068. if (length == 0) {
    1069. return "";
    1070. }
    1071. if (hasByteArray()) {
    1072. //noinspection deprecation
    1073. return new String(byteArray(), 0, byteArrayOffset() + index, length);
    1074. }
    1075. char[] chars = new char[length];
    1076. for (int pos = index; pos < length; pos++) {
    1077. chars[pos] = (char) (getByteUnchecked(pos) & 0x7F);
    1078. }
    1079. return new String(chars);
    1080. }
    1081. /**
    1082. * Decodes the a portion of this slice into a string with the specified
    1083. * character set name.
    1084. */
    1085. public String toString(int index, int length, Charset charset)
    1086. {
    1087. if (length == 0) {
    1088. return "";
    1089. }
    1090. if (hasByteArray()) {
    1091. return new String(byteArray(), byteArrayOffset() + index, length, charset);
    1092. }
    1093. return new String(getBytes(index, length), charset);
    1094. }
    1095. public ByteBuffer toByteBuffer()
    1096. {
    1097. return toByteBuffer(0, size);
    1098. }
    1099. public ByteBuffer toByteBuffer(int index, int length)
    1100. {
    1101. checkIndexLength(index, length);
    1102. if (length() == 0) {
    1103. return EMPTY_BYTE_BUFFER;
    1104. }
    1105. if (hasByteArray()) {
    1106. return ByteBuffer.wrap(byteArray(), byteArrayOffset() + index, length).slice();
    1107. }
    1108. if ((reference instanceof ByteBuffer) && ((ByteBuffer) reference).isDirect()) {
    1109. ByteBuffer buffer = (ByteBuffer) reference;
    1110. int position = toIntExact(address - bufferAddress(buffer)) + index;
    1111. buffer = buffer.duplicate();
    1112. buffer.position(position);
    1113. buffer.limit(position + length);
    1114. return buffer.slice();
    1115. }
    1116. throw new UnsupportedOperationException("Conversion to ByteBuffer not supported for this Slice");
    1117. }
    1118. /**
    1119. * Decodes the a portion of this slice into a string with the specified
    1120. * character set name.
    1121. */
    1122. @Override
    1123. public String toString()
    1124. {
    1125. StringBuilder builder = new StringBuilder("Slice{");
    1126. if (base != null) {
    1127. builder.append("base=").append(identityToString(base)).append(", ");
    1128. }
    1129. builder.append("address=").append(address);
    1130. builder.append(", length=").append(length());
    1131. builder.append('}');
    1132. return builder.toString();
    1133. }
    1134. private static String identityToString(Object o)
    1135. {
    1136. if (o == null) {
    1137. return null;
    1138. }
    1139. return o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o));
    1140. }
    1141. private static void copyMemory(Object src, long srcAddress, Object dest, long destAddress, int length)
    1142. {
    1143. // The Unsafe Javadoc specifies that the transfer size is 8 iff length % 8 == 0
    1144. // so ensure that we copy big chunks whenever possible, even at the expense of two separate copy operations
    1145. int bytesToCopy = length - (length % 8);
    1146. unsafe.copyMemory(src, srcAddress, dest, destAddress, bytesToCopy);
    1147. unsafe.copyMemory(src, srcAddress + bytesToCopy, dest, destAddress + bytesToCopy, length - bytesToCopy);
    1148. }
    1149. private void checkIndexLength(int index, int length)
    1150. {
    1151. checkPositionIndexes(index, index + length, length());
    1152. }
    1153. //
    1154. // The following methods were forked from Guava primitives
    1155. //
    1156. private static long fillLong(byte value)
    1157. {
    1158. return (value & 0xFFL) << 56
    1159. | (value & 0xFFL) << 48
    1160. | (value & 0xFFL) << 40
    1161. | (value & 0xFFL) << 32
    1162. | (value & 0xFFL) << 24
    1163. | (value & 0xFFL) << 16
    1164. | (value & 0xFFL) << 8
    1165. | (value & 0xFFL);
    1166. }
    1167. private static int compareUnsignedBytes(byte thisByte, byte thatByte)
    1168. {
    1169. return unsignedByteToInt(thisByte) - unsignedByteToInt(thatByte);
    1170. }
    1171. private static int unsignedByteToInt(byte thisByte)
    1172. {
    1173. return thisByte & 0xFF;
    1174. }
    1175. /**
    1176. * Turns a long representing a sequence of 8 bytes read in little-endian order
    1177. * into a number that when compared produces the same effect as comparing the
    1178. * original sequence of bytes lexicographically
    1179. */
    1180. private static long longBytesToLong(long bytes)
    1181. {
    1182. return Long.reverseBytes(bytes) ^ Long.MIN_VALUE;
    1183. }
    1184. }