@@ -285,7 +285,32 @@ public BitBuffer putShort(int s, ByteOrder order) {
285
285
var value = (short ) s ;
286
286
return putBits (order == ByteOrder .BIG_ENDIAN ? Short .reverseBytes (value ) : value , Short .SIZE );
287
287
}
288
-
288
+
289
+ /**
290
+ * Given the specified {@code maxValue}, this method writes the specified value to this {@link BitBuffer}
291
+ * using the optimal amount of bits, thus providing free compression.
292
+ *
293
+ * @param value the value to write to this {@link BitBuffer}.
294
+ * @param maxValue the maximum possible value that {@code value} can be; a lower {@code maxValue} results in a
295
+ * better compression ratio.
296
+ * @return this {@link BitBuffer} to allow for the convenience of method-chaining.
297
+ * @throws IllegalArgumentException if {@code maxValue} is negative or if the absolute value of {@code value} is
298
+ * greater than {@code maxValue}.
299
+ */
300
+ public BitBuffer putValue (long value , long maxValue ) throws IllegalArgumentException {
301
+ if (maxValue < 0 ) {
302
+ throw new IllegalArgumentException ("maxValue must be positive!" );
303
+ }
304
+
305
+ if (Math .abs (value ) > maxValue ) {
306
+ throw new IllegalArgumentException ("value must be less than or equal to maxValue!" );
307
+ }
308
+
309
+ int numBits = Long .SIZE - Long .numberOfLeadingZeros (maxValue ) + 1 ;
310
+
311
+ return putBits (value , numBits );
312
+ }
313
+
289
314
/**
290
315
* After a series of relative {@code put} operations, flip the <i>cache</i> to prepare for a series of relative
291
316
* {@code get} operations.
@@ -499,6 +524,28 @@ public short getShort(ByteOrder order) {
499
524
return order == ByteOrder .BIG_ENDIAN ? Short .reverseBytes (value ) : value ;
500
525
}
501
526
527
+ /**
528
+ * Given the specified {@code maxValue}, this method reads a value from this {@link BitBuffer} using the optimal
529
+ * amount of bits, thus providing free compression.
530
+ * <br><br>
531
+ * The value of {@code maxValue} should be the same as what was used when calling {@link #putValue(long, long)}.
532
+ *
533
+ * @param maxValue the maximum possible value that the value being read can be; a lower {@code maxValue} results
534
+ * in a better compression ratio.
535
+ * @return the value read from this {@link BitBuffer} as a {@code long}.
536
+ * @throws IllegalArgumentException if {@code maxValue} is negative.
537
+ */
538
+ public long getValue (long maxValue ) {
539
+ if (maxValue < 0 ) {
540
+ throw new IllegalArgumentException ("maxValue must be positive!" );
541
+ }
542
+
543
+ int numBits = Long .SIZE - Long .numberOfLeadingZeros (maxValue ) + 1 ;
544
+ int unused = Long .SIZE - numBits ;
545
+
546
+ return getBits (numBits ) << unused >> unused ;
547
+ }
548
+
502
549
/**
503
550
* Gets the capacity of the backing {@link ByteBuffer}.
504
551
*
0 commit comments