From a7941b92e29f90b071139efa87c01dc379597fcf Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 15 Feb 2016 22:53:39 +0100 Subject: [PATCH] added BitReader::readUnsignedExpGolombCodedBits() and BitReader::readSignedExpGolombCodedBits() --- CMakeLists.txt | 4 ++-- c++utilities.pro | 2 +- io/binaryreader.h | 4 ++-- io/bitreader.h | 37 ++++++++++++++++++++++++++++++++++++- tests/iotests.cpp | 8 ++++++-- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05eefec..ea10920 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,8 +66,8 @@ set(META_APP_AUTHOR "Martchus") set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}") set(META_APP_DESCRIPTION "Common C++ classes and routines used by my applications such as argument parser, IO and conversion utilities.") set(META_VERSION_MAJOR 3) -set(META_VERSION_MINOR 1) -set(META_VERSION_PATCH 1) +set(META_VERSION_MINOR 2) +set(META_VERSION_PATCH 0) set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}) # stringification of meta data diff --git a/c++utilities.pro b/c++utilities.pro index b5390d1..f12b7a2 100644 --- a/c++utilities.pro +++ b/c++utilities.pro @@ -3,7 +3,7 @@ projectname = c++utilities appname = "C++ Utilities" appauthor = Martchus QMAKE_TARGET_DESCRIPTION = "Common C++ classes and routines used by my applications such as argument parser, IO and conversion utilities." -VERSION = 3.1.1 +VERSION = 3.2.0 # include ../../common.pri when building as part of a subdirs project; otherwise include general.pri !include(../../common.pri) { diff --git a/io/binaryreader.h b/io/binaryreader.h index 9424a1b..0804b05 100644 --- a/io/binaryreader.h +++ b/io/binaryreader.h @@ -160,7 +160,7 @@ inline bool BinaryReader::fail() const */ inline bool BinaryReader::eof() const { - return m_stream ? m_stream->eof() : false; + return m_stream && m_stream->eof(); } /*! @@ -168,7 +168,7 @@ inline bool BinaryReader::eof() const */ inline bool BinaryReader::canRead() const { - return m_stream ? !(m_stream->fail() || m_stream->eof()) : false; + return m_stream && m_stream->good(); } /*! diff --git a/io/bitreader.h b/io/bitreader.h index 2dabde6..10721be 100644 --- a/io/bitreader.h +++ b/io/bitreader.h @@ -5,8 +5,8 @@ #include "../application/global.h" #include - #include +#include namespace IoUtilities { @@ -18,6 +18,8 @@ public: template intType readBits(byte bitCount); byte readBit(); + template intType readUnsignedExpGolombCodedBits(); + template intType readSignedExpGolombCodedBits(); template intType showBits(byte bitCount); void skipBits(std::size_t bitCount); void align(); @@ -88,6 +90,39 @@ inline byte BitReader::readBit() return readBits(1) == 1; } +/*! + * \brief Reads "Exp-Golomb coded" bits (unsigned). + * \tparam intType Specifies the type of the returned value. + * \remarks Does not check whether intType is big enough to hold result. + * \throws Throws ios_base::failure if the end of the buffer is exceeded. + * The reader becomes invalid in that case. + * \sa https://en.wikipedia.org/wiki/Exponential-Golomb_coding + */ +template +intType BitReader::readUnsignedExpGolombCodedBits() +{ + byte count = 0; + while(!readBit()) { + ++count; + } + return count ? (((1 << count) | readBits(count)) - 1) : 0; +} + +/*! + * \brief Reads "Exp-Golomb coded" bits (signed). + * \tparam intType Specifies the type of the returned value which should be signed (obviously). + * \remarks Does not check whether intType is big enough to hold result. + * \throws Throws ios_base::failure if the end of the buffer is exceeded. + * The reader becomes invalid in that case. + * \sa https://en.wikipedia.org/wiki/Exponential-Golomb_coding + */ +template +intType BitReader::readSignedExpGolombCodedBits() +{ + auto value = readUnsignedExpGolombCodedBits::type>(); + return (value % 2) ? static_cast((value + 1) / 2) : (-static_cast(value / 2)); +} + /*! * \brief Reads the specified number of bits from the buffer without advancing the current position. */ diff --git a/tests/iotests.cpp b/tests/iotests.cpp index 061faca..d9b9a8a 100644 --- a/tests/iotests.cpp +++ b/tests/iotests.cpp @@ -181,8 +181,8 @@ void IoTests::testBinaryWriter() */ void IoTests::testBitReader() { - byte testData[] = {0x81, 0x90, 0x3C, 0x44, 0x28, 0x00, 0x44}; - BitReader reader(reinterpret_cast(testData), sizeof(testData)); + const byte testData[] = {0x81, 0x90, 0x3C, 0x44, 0x28, 0x00, 0x44, 0x10, 0x20}; + BitReader reader(reinterpret_cast(testData), sizeof(testData)); CPPUNIT_ASSERT(reader.readBit() == 1); reader.skipBits(6); CPPUNIT_ASSERT(reader.showBits(2) == 3); @@ -190,6 +190,10 @@ void IoTests::testBitReader() CPPUNIT_ASSERT(reader.readBits(32) == (0x103C4428 << 1)); reader.align(); CPPUNIT_ASSERT(reader.readBits(8) == 0x44); + CPPUNIT_ASSERT(reader.readUnsignedExpGolombCodedBits() == 7); + CPPUNIT_ASSERT(reader.readSignedExpGolombCodedBits() == 4); + CPPUNIT_ASSERT(reader.readBit() == 0); + CPPUNIT_ASSERT(reader.readBit() == 0); CPPUNIT_ASSERT_THROW(reader.readBit(), std::ios_base::failure); }