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 @@ +