diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d712165 --- /dev/null +++ b/.gitignore @@ -0,0 +1,136 @@ +# Created by .ignore support plugin (hsz.mobi) +### Java template + +# Manually Amended +# Target folders +target + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Windows template +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# Manually Amended +.idea + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle EXTENDED +.gradle +/build + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +.idea/artifacts +.idea/compiler.xml +.idea/jarRepositories.xml +.idea/modules.xml +.idea/*.iml +.idea/modules +*.iml +*.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser diff --git a/build.gradle b/build.gradle index df024c3..4675486 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ repositories { } dependencies { - testCompile group: 'junit', name: 'junit', version: '4.0' + testCompile group: 'junit', name: 'junit', version: '4.13.1' } compileJava { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dd2cbe1..9bb5c92 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jul 06 16:26:07 CEST 2014 +#Tue Jan 19 21:06:07 CET 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip diff --git a/src/main/java/net/magik6k/bitbuffer/ArrayBitBuffer.java b/src/main/java/net/magik6k/bitbuffer/ArrayBitBuffer.java index dd2f819..a3152e8 100644 --- a/src/main/java/net/magik6k/bitbuffer/ArrayBitBuffer.java +++ b/src/main/java/net/magik6k/bitbuffer/ArrayBitBuffer.java @@ -1,7 +1,7 @@ package net.magik6k.bitbuffer; class ArrayBitBuffer extends SimpleBitBuffer{ - private byte[] bytes; + private final byte[] bytes; protected ArrayBitBuffer(long bits) { bytes = new byte[(int) Math.ceil(bits / 8.d)]; diff --git a/src/main/java/net/magik6k/bitbuffer/BitBuffer.java b/src/main/java/net/magik6k/bitbuffer/BitBuffer.java index 292ed0e..f1a8f18 100644 --- a/src/main/java/net/magik6k/bitbuffer/BitBuffer.java +++ b/src/main/java/net/magik6k/bitbuffer/BitBuffer.java @@ -44,7 +44,18 @@ public BitBuffer putBit(boolean bit){ * @return This buffer */ public abstract BitBuffer putByte(byte b, int bits); - + + /** + * Puts signed short value(16 bits) + * @param i value to set + * @return This buffer + */ + public BitBuffer putShort(short i){ + putByte((byte)((i&0xFF00)>>>8)); + putByte((byte) (i&0x00FF)); + return this; + } + /** * Puts signed integer value(32 bits) * @param i value to set @@ -74,7 +85,28 @@ public BitBuffer putLong(long l){ putByte((byte) (l&0x00000000000000FFL)); return this; } - + + /** + * Puts short value with specified bit count. Note that this + * method can be used with both signed and unsigned data. + * @param i value to set + * @param bits Number of bits to use + * @return This buffer + */ + public BitBuffer putShort(short i, int bits){ + if(bits == 0)return this; + do{ + if(bits > 7){ + putByte((byte) ((i&(0xFF << (bits - 8))) >>> (bits - 8) )); + bits -= 8; + }else{ + putByte((byte) (i & (0xFF >> -(bits - 8))), bits); + bits = 0; + } + }while(bits > 0); + return this; + } + /** * Puts integer value with specified bit count. Note that this * method can be used with both signed and unsigned data. @@ -206,7 +238,16 @@ public BitBuffer put(boolean bit){ public BitBuffer put(byte number){ return putByte(number); } - + + /** + * @see #putShort(short) + * @param number value to set + * @return This buffer + */ + public BitBuffer put(short number) { + return putShort(number); + } + /** * @see #putInt(int) * @param number value to set @@ -234,7 +275,16 @@ public BitBuffer put(long number) { public BitBuffer put(byte number, int bits){ return putByte(number, bits); } - + + /** + * @see #putShort(short) + * @param number value to set + * @return This buffer + */ + public BitBuffer put(short number, int bits) { + return putShort(number, bits); + } + /** * @see #putInt(int) * @param number value to set @@ -296,7 +346,7 @@ public BitBuffer put(BitBuffer buffer){ * @return This buffer */ public BitBuffer put(ByteBuffer buffer){ - while(buffer.remaining() > 1){ + while(buffer.hasRemaining()){ this.put(buffer.get()); } return this; @@ -310,7 +360,7 @@ public BitBuffer put(ByteBuffer buffer){ * @return This buffer */ public BitBuffer put(boolean[] array, int offset, int limit){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset]); } return this; @@ -334,7 +384,7 @@ public BitBuffer put(boolean[] array) { * @return This buffer */ public BitBuffer put(byte[] array, int offset, int limit){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset]); } return this; @@ -358,7 +408,7 @@ public BitBuffer put(byte[] array) { * @return This buffer */ public BitBuffer put(int[] array, int offset, int limit){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset]); } return this; @@ -382,7 +432,7 @@ public BitBuffer put(int[] array) { * @return This buffer */ public BitBuffer put(long[] array, int offset, int limit){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset]); } return this; @@ -407,7 +457,7 @@ public BitBuffer put(long[] array) { * @return This buffer */ public BitBuffer put(byte[] array, int offset, int limit, int bits){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset], bits); } return this; @@ -433,7 +483,7 @@ public BitBuffer put(byte[] array, int bits) { * @return This buffer */ public BitBuffer put(int[] array, int offset, int limit, int bits){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset], bits); } return this; @@ -459,7 +509,7 @@ public BitBuffer put(int[] array, int bits) { * @return This buffer */ public BitBuffer put(long[] array, int offset, int limit, int bits){ - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { put(array[offset], bits); } return this; @@ -507,14 +557,63 @@ public BitBuffer put(IBufferInsert data){ * @return Unsigned Byte value of given bit width */ public abstract byte getByteUnsigned(int bits); - + + /** + * @return 16 bit signed short value + */ + public int getShort(){ + return (((getByte()&0xFF) << 8) | (getByte()&0xFF)); + } + + /** + * @param bits Length of short + * @return Short value of given bit width + */ + public int getShort(int bits){ + if(bits == 0)return 0; + boolean sign = getBoolean(); + int inBits = --bits; + + int res = 0; + do { + if(bits > 7){ + res = (res << 8) | (getByte()&0xFF); + bits -= 8; + }else{ + res = (res << bits) + (getByteUnsigned(bits)&0xFF); + bits -= bits; + } + }while(bits > 0); + + return (short) (sign ? (0xFFFFFFFF << inBits) | res : res); + } + + /** + * @param bits Length of short + * @return Unsigned Short value of given bit width + */ + public short getShortUnsigned(int bits){ + if(bits == 0)return 0; + short res = 0; + do { + if(bits > 7){ + res = (short) ((res << 8) | (getByte()&0xFF)); + bits -= 8; + }else{ + res = (short) ((res << bits) + (getByteUnsigned(bits)&0xFF)); + bits -= bits; + } + }while(bits > 0); + return res; + } + /** * @return 32 bit signed integer value */ public int getInt(){ return ((getByte()&0xFF) << 24) | ((getByte()&0xFF) << 16) | ((getByte()&0xFF) << 8) | (getByte()&0xFF); } - + /** * @param bits Length of integer * @return Signed integer value of given bit width @@ -680,7 +779,7 @@ public String getString(int length, Charset charset, int bitsPerChar){ * @return Given array */ public boolean[] get(boolean[] dst, int offset, int limit) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getBoolean(); } return dst; @@ -703,7 +802,7 @@ public boolean[] get(boolean[] dst) { * @return Given array */ public byte[] get(byte[] dst, int offset, int limit) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getByte(); } return dst; @@ -726,7 +825,7 @@ public byte[] get(byte[] dst) { * @return Given array */ public int[] get(int[] dst, int offset, int limit) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getInt(); } return dst; @@ -749,7 +848,7 @@ public int[] get(int[] dst) { * @return Given array */ public long[] get(long[] dst, int offset, int limit) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getLong(); } return dst; @@ -773,7 +872,7 @@ public long[] get(long[] dst) { * @return Given array */ public byte[] get(byte[] dst, int offset, int limit, int bits) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getByte(bits); } return dst; @@ -798,7 +897,7 @@ public byte[] get(byte[] dst, int bits) { * @return Given array */ public int[] get(int[] dst, int offset, int limit, int bits) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getInt(bits); } return dst; @@ -823,7 +922,7 @@ public int[] get(int[] dst, int bits) { * @return Given array */ public long[] get(long[] dst, int offset, int limit, int bits) { - for(; offset > limit; ++offset) { + for(; offset < limit; ++offset) { dst[offset] = getLong(bits); } return dst; diff --git a/src/main/java/net/magik6k/bitbuffer/SimpleBitBuffer.java b/src/main/java/net/magik6k/bitbuffer/SimpleBitBuffer.java index ac95154..fed0310 100644 --- a/src/main/java/net/magik6k/bitbuffer/SimpleBitBuffer.java +++ b/src/main/java/net/magik6k/bitbuffer/SimpleBitBuffer.java @@ -103,12 +103,12 @@ public boolean canWrite() { @Override public long size() { - return rawLength(); + return rawLength() * Byte.SIZE; } @Override public long limit() { - return read ? limit : rawLength(); + return read ? limit : rawLength() * Byte.SIZE; } @Override diff --git a/src/test/java/net/magik6k/bitbuffer/BitBufferTest.java b/src/test/java/net/magik6k/bitbuffer/BitBufferTest.java index 9b26d35..d0c5501 100644 --- a/src/test/java/net/magik6k/bitbuffer/BitBufferTest.java +++ b/src/test/java/net/magik6k/bitbuffer/BitBufferTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.*; import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; import net.magik6k.bitbuffer.BitBuffer; @@ -61,8 +62,8 @@ public void doubleTest(){ buffer.flip(); - assertEquals(1234567890.12345, buffer.getDouble()); - assertEquals(4572145.34653625, buffer.getDouble()); + assertEquals(1234567890.12345, buffer.getDouble(), 0.0F); + assertEquals(4572145.34653625, buffer.getDouble(), 0.0F); } @Test @@ -191,7 +192,42 @@ public void basicIntegerTest(){ assertHex(-2346798, buffer.getInt()); assertHex(29, buffer.getInt()); } - + + @Test + public void basicShortTest(){ + BitBuffer buffer = BitBuffer.allocate(128); + + buffer.putShort((short) 0xF1F1); + buffer.putShort((short) 0x0910); + buffer.putShort((short) 29); + + buffer.flip(); + + assertHex(0xF1F1, buffer.getShort()); + assertHex(0x0910, buffer.getShort()); + assertHex(29, buffer.getShort()); + } + + @Test + public void basicByteBufferTest(){ + ByteBuffer byteBuffer = ByteBuffer.allocate(4); + BitBuffer bitBuffer = BitBuffer.allocate(128); + + byteBuffer.put((byte) 0x12); + byteBuffer.put((byte) 0x15); + byteBuffer.put((byte) 0x09); + byteBuffer.put((byte) 0x99); + byteBuffer.rewind(); + + bitBuffer.put(byteBuffer); + bitBuffer.flip(); + + assertBits((byte)0x12, bitBuffer.getByte()); + assertBits((byte)0x15, bitBuffer.getByte()); + assertBits((byte)0x09, bitBuffer.getByte()); + assertBits((byte)0x99, bitBuffer.getByte()); + } + @Test public void mixedByteTest(){ BitBuffer buffer = BitBuffer.allocate(16); @@ -430,6 +466,15 @@ public void arrayLength() { assertEquals(2, buffer.asByteArray().length); } + @Test + public void arrayPutBooleanTest() { + BitBuffer buffer = BitBuffer.allocate(8); + buffer.put(new boolean[] { true, false, true, true, false, false, true, true }); + assertEquals(8, buffer.position()); + buffer.flip(); + assertArrayEquals(buffer.asByteArray(), new byte[] { (byte) 0b10110011} ); + } + public static void assertHex(long expected, long actual){ if(expected != actual) throw new AssertionError("expected:<"+"0x" + Long.toHexString(expected)