diff --git a/CUETools.Codecs/BitWriter.cs b/CUETools.Codecs/BitWriter.cs
index 707c796..71ed7d4 100644
--- a/CUETools.Codecs/BitWriter.cs
+++ b/CUETools.Codecs/BitWriter.cs
@@ -139,7 +139,7 @@ namespace CUETools.Codecs
//assert(bits == 32 || val < (1U << bits));
if (bits == 0 || eof) return;
- if (bits <= bit_left_m)
+ if (bits < bit_left_m)
{
bit_left_m -= bits;
bit_buf_m |= val << bit_left_m;
@@ -174,8 +174,10 @@ namespace CUETools.Codecs
buffer[buf_ptr_m + 0] = (byte)(bb & 0xFF);
buf_ptr_m += 8;
}
- bit_left_m = 64 + bit_left_m - bits;
- bit_buf_m = val << bit_left_m;
+ // cannot do this in one shift, because bit_left_m can be 64,
+ //
+ bit_left_m += 64 - bits;
+ bit_buf_m = bit_left_m == 64 ? 0 : val << bit_left_m;
}
}
@@ -284,7 +286,7 @@ namespace CUETools.Codecs
// write quotient in unary
int q = (v >> k) + 1;
int bits = k + q;
- while (bits > 56)
+ while (bits > 64)
{
#if DEBUG
if (buf + 1 > fixedbuf + buf_end)
@@ -302,7 +304,7 @@ namespace CUETools.Codecs
// write remainder in binary using 'k' bits
//writebits_fast(k + q, (uint)((v & ((1 << k) - 1)) | (1 << k)), ref buf);
ulong val = (uint)((v & ((1 << k) - 1)) | (1 << k));
- if (bits <= bit_left)
+ if (bits < bit_left)
{
bit_left -= bits;
bit_buf |= val << bit_left;
@@ -335,8 +337,8 @@ namespace CUETools.Codecs
*(buf++) = (byte)(bb >> 16);
*(buf++) = (byte)(bb >> 8);
*(buf++) = (byte)(bb);
- bit_left = 64 + bit_left - bits;
- bit_buf = val << bit_left;
+ bit_left += 64 - bits;
+ bit_buf = (val << bit_left - 1) << 1;
}
}
crc16_m = crc16;
diff --git a/CUETools/CUETools.TestCodecs/BitWriterTest.cs b/CUETools/CUETools.TestCodecs/BitWriterTest.cs
new file mode 100644
index 0000000..13e5f29
--- /dev/null
+++ b/CUETools/CUETools.TestCodecs/BitWriterTest.cs
@@ -0,0 +1,106 @@
+using CUETools.Codecs;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+
+namespace CUETools.TestCodecs
+{
+
+
+ ///
+ ///This is a test class for BitWriterTest and is intended
+ ///to contain all BitWriterTest Unit Tests
+ ///
+ [TestClass()]
+ public class BitWriterTest
+ {
+
+
+ private TestContext testContextInstance;
+
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get
+ {
+ return testContextInstance;
+ }
+ set
+ {
+ testContextInstance = value;
+ }
+ }
+
+ #region Additional test attributes
+ //
+ //You can use the following additional attributes as you write your tests:
+ //
+ //Use ClassInitialize to run code before running the first test in the class
+ //[ClassInitialize()]
+ //public static void MyClassInitialize(TestContext testContext)
+ //{
+ //}
+ //
+ //Use ClassCleanup to run code after all tests in a class have run
+ //[ClassCleanup()]
+ //public static void MyClassCleanup()
+ //{
+ //}
+ //
+ //Use TestInitialize to run code before running each test
+ //[TestInitialize()]
+ //public void MyTestInitialize()
+ //{
+ //}
+ //
+ //Use TestCleanup to run code after each test has run
+ //[TestCleanup()]
+ //public void MyTestCleanup()
+ //{
+ //}
+ //
+ #endregion
+
+
+ ///
+ ///A test for writebits
+ ///
+ [TestMethod()]
+ public void writebitsTest()
+ {
+ byte[] buf = new byte[0x10000];
+ for (int seed = 0; seed < 10; seed++)
+ {
+ BitWriter target = new BitWriter(buf, 0, buf.Length);
+ var rnd = new Random(seed);
+ int count = 0;
+ do
+ {
+ int bits = rnd.Next(0, 64) + 1;
+ ulong val = (1U << (bits - 1));
+ target.writebits(bits, val);
+ count++;
+ }
+ while (target.Length < buf.Length - 32);
+ target.flush();
+ rnd = new Random(seed);
+ unsafe
+ {
+ fixed (byte* ptr = buf)
+ {
+ BitReader reader = new BitReader(ptr, 0, buf.Length);
+ for (int i = 0; i < count; i++)
+ {
+ int bits = rnd.Next(0, 64) + 1;
+ ulong val = (1U << (bits - 1));
+ ulong val1 = reader.readbits64(bits);
+ Assert.AreEqual(val, val1, string.Format("i = {0}, bits = {1}, seed = {2}, pos = {3}", i, bits, seed, reader.Position));
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj
index 2955a6b..b0da770 100644
--- a/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj
+++ b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj
@@ -66,6 +66,7 @@
+