#include "bitinput.h" #include "bitoutput.h" #include #include #include namespace NBitIO { static const char BITS_REF[] = "00100010 01000000 00000000 00100111 11011111 01100111 11010101 00010100 " "00100010 01100011 11100011 00110000 11011011 11011111 01001100 00110101 " "10011110 01011111 01010000 00000110 00011011 00100110 00010100 01110011 " "00001010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 " "10110101 01010101 01010101 01010101 01010101 01010101 01010101 01010101 " "01000000"; inline ui64 Bits(ui64 bytes) { return bytes << 3ULL; } inline TString PrintBits(const char* a, const char* b, bool reverse = false) { TString s; TStringOutput out(s); for (const char* it = a; it != b; ++it) { if (it != a) out << ' '; ui8 byte = *it; if (reverse) byte = ReverseBits(byte); for (ui32 mask = 1; mask < 0xff; mask <<= 1) { out << ((byte & mask) ? '1' : '0'); } } return s; } template inline TString PrintBits(T t, ui32 bits = Bits(sizeof(T))) { return PrintBits((char*)&t, ((char*)&t) + BytesUp(bits)); } } class TBitIOTest: public TTestBase { UNIT_TEST_SUITE(TBitIOTest); UNIT_TEST(TestBitIO) UNIT_TEST_SUITE_END(); private: using TBi = NBitIO::TBitInput; using TVec = TVector; void static CheckBits(const TVec& v, const TString& ref, const TString& rem) { UNIT_ASSERT_VALUES_EQUAL_C(NBitIO::PrintBits(v.begin(), v.end()), ref, rem); } void DoRead(TBi& b, ui32& t) { b.Read(t, 1, 0); // 1 b.ReadK<3>(t, 1); // 4 b.Read(t, 5, 4); // 9 b.ReadK<14>(t, 9); // 23 b.Read(t, 1, 23); // 24 b.ReadK<5>(t, 24); // 29 b.Read(t, 3, 29); // 32 } template void DoWrite(TBo& b, ui32 t) { b.Write(t, 1, 0); //1 b.Write(t, 3, 1); //4 b.Write(t, 5, 4); //9 b.Write(t, 14, 9); //23 b.Write(t, 1, 23); //24 b.Write(t, 5, 24); //29 b.Write(t, 3, 29); //32 } template void DoWrite1(TBo& out, const TString& rem) { out.Write(0x0C, 3); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 1u, (rem + ", " + ToString(__LINE__))); out.Write(0x18, 4); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 1u, (rem + ", " + ToString(__LINE__))); out.Write(0x0C, 3); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 2u, (rem + ", " + ToString(__LINE__))); out.Write(0x30000, 17); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 4u, (rem + ", " + ToString(__LINE__))); out.Write(0x0C, 3); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 4u, (rem + ", " + ToString(__LINE__))); } template void DoWrite2(TBo& out, const TString& rem) { out.Write(0x0C, 3); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 8u, (rem + ", " + ToString(__LINE__))); out.Write(0x42, 7); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 9u, (rem + ", " + ToString(__LINE__))); DoWrite(out, 1637415112); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 13u, (rem + ", " + ToString(__LINE__))); DoWrite(out, 897998715); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 17u, (rem + ", " + ToString(__LINE__))); DoWrite(out, 201416527); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 21u, (rem + ", " + ToString(__LINE__))); DoWrite(out, 432344219); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 25u, (rem + ", " + ToString(__LINE__))); out.Write(0xAAAAAAAAAAAAAAAAULL, 64); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 33u, (rem + ", " + ToString(__LINE__))); out.Write(0x5555555555555555ULL, 64); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 41u, (rem + ", " + ToString(__LINE__))); } void DoBitOutput(NBitIO::TBitOutputYVector& out, const TString& rem) { DoWrite1(out, rem); out.WriteWords<8>(0xabcdef); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 8u, (rem + ", " + ToString(__LINE__))); DoWrite2(out, rem); } void DoBitOutput(NBitIO::TBitOutputArray& out, const TString& rem) { DoWrite1(out, rem); out.WriteWords<8>(0xabcdef); UNIT_ASSERT_VALUES_EQUAL_C(out.GetOffset(), 8u, (rem + ", " + ToString(__LINE__))); DoWrite2(out, rem); } void DoBitInput(TBi& in, const TString& rem) { UNIT_ASSERT(!in.Eof()); { ui64 val; val = 0; UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 0u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(in.Read(val, 3), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 1u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; UNIT_ASSERT_C(in.Read(val, 4), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x8u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 1u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; UNIT_ASSERT_C(in.Read(val, 3), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 2u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; UNIT_ASSERT_C(in.Read(val, 17), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x10000u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 4u, (rem + ": " + NBitIO::PrintBits(val))); { ui32 rt = 0; in.ReadRandom(30, rt, 10, 20); UNIT_ASSERT_STRINGS_EQUAL(NBitIO::PrintBits(rt).data(), "00000000 00000000 00001111 01111100"); } val = 0; UNIT_ASSERT_C(in.Read(val, 3), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; UNIT_ASSERT_C(in.ReadWords<8>(val), (rem + ": " + NBitIO::PrintBits(val)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0xabcdefU, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 8u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; UNIT_ASSERT_C(in.Read(val, 3), (rem + ", " + ToString(__LINE__)).data()); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x4u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 8u, (rem + ": " + NBitIO::PrintBits(val))); UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); val = 0; in.Read(val, 7); UNIT_ASSERT_VALUES_EQUAL_C(val, 0x42u, (rem + ": " + NBitIO::PrintBits(val))); } { ui32 v = 0; DoRead(in, v); UNIT_ASSERT_VALUES_EQUAL_C(v, 1637415112ul, (rem + ": " + NBitIO::PrintBits(v))); DoRead(in, v); UNIT_ASSERT_VALUES_EQUAL_C(v, 897998715u, (rem + ": " + NBitIO::PrintBits(v))); DoRead(in, v); UNIT_ASSERT_VALUES_EQUAL_C(v, 201416527u, (rem + ": " + NBitIO::PrintBits(v))); DoRead(in, v); UNIT_ASSERT_VALUES_EQUAL_C(v, 432344219u, (rem + ": " + NBitIO::PrintBits(v))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 25u, (rem + ": " + NBitIO::PrintBits(v))); } { ui64 v8 = 0; in.ReadSafe(v8, 64); UNIT_ASSERT_VALUES_EQUAL_C(v8, 0xAAAAAAAAAAAAAAAAULL, (rem + ": " + NBitIO::PrintBits(v8))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 33u, (rem + ": " + NBitIO::PrintBits(v8))); v8 = 0; in.ReadK<64>(v8); UNIT_ASSERT_VALUES_EQUAL_C(v8, 0x5555555555555555ULL, (rem + ": " + NBitIO::PrintBits(v8))); UNIT_ASSERT_VALUES_EQUAL_C(in.GetOffset(), 41u, (rem + ": " + NBitIO::PrintBits(v8))); } ui32 v = 0; UNIT_ASSERT_C(!in.Eof(), (rem + ", " + ToString(__LINE__)).data()); UNIT_ASSERT_C(in.Read(v, 5), (rem + ", " + ToString(__LINE__)).data()); UNIT_ASSERT_C(in.Eof(), (rem + ", " + ToString(__LINE__)).data()); } void TestBitIO() { { TVec vec; { NBitIO::TBitOutputYVector out(&vec); DoBitOutput(out, ToString(__LINE__)); } CheckBits(vec, NBitIO::BITS_REF, ToString(__LINE__).data()); { TBi in(vec); DoBitInput(in, ToString(__LINE__)); } } { TVec vec; vec.resize(41, 0); { NBitIO::TBitOutputArray out(vec.begin(), vec.size()); DoBitOutput(out, ToString(__LINE__)); } CheckBits(vec, NBitIO::BITS_REF, ToString(__LINE__).data()); { TBi in(vec); DoBitInput(in, ToString(__LINE__)); } } } }; UNIT_TEST_SUITE_REGISTRATION(TBitIOTest);