diff --git a/Foundation/include/Poco/BinaryReader.h b/Foundation/include/Poco/BinaryReader.h index 21f5380c9..a52707388 100644 --- a/Foundation/include/Poco/BinaryReader.h +++ b/Foundation/include/Poco/BinaryReader.h @@ -23,6 +23,7 @@ #include "Poco/Foundation.h" #include "Poco/Buffer.h" #include "Poco/MemoryStream.h" +#include "Poco/ByteOrder.h" #include #include @@ -151,6 +152,32 @@ public: /// Returns the number of available bytes in the stream. private: + template + BinaryReader& read(T& value, bool flipBytes) + { + _istr.read((char*) &value, sizeof(value)); + if (flipBytes) value = ByteOrder::flipBytes(value); + return *this; + } + + template + void read7BitEncoded(T& value) + { + char c; + value = 0; + int s = 0; + do + { + c = 0; + _istr.read(&c, 1); + T x = (c & 0x7F); + x <<= s; + value += x; + s += 7; + } + while (c & 0x80); + } + std::istream& _istr; bool _flipBytes; TextConverter* _pTextConverter; diff --git a/Foundation/include/Poco/BinaryWriter.h b/Foundation/include/Poco/BinaryWriter.h index d39e6b8f8..1d87df9ba 100644 --- a/Foundation/include/Poco/BinaryWriter.h +++ b/Foundation/include/Poco/BinaryWriter.h @@ -23,6 +23,7 @@ #include "Poco/Foundation.h" #include "Poco/Buffer.h" #include "Poco/MemoryStream.h" +#include "Poco/ByteOrder.h" #include #include @@ -160,6 +161,36 @@ public: /// either BIG_ENDIAN_BYTE_ORDER or LITTLE_ENDIAN_BYTE_ORDER. private: + template + BinaryWriter& write(T value, bool flipBytes) + { + if (flipBytes) + { + T fValue = ByteOrder::flipBytes(value); + _ostr.write((const char*) &fValue, sizeof(fValue)); + } + else + { + _ostr.write((const char*) &value, sizeof(value)); + } + return *this; + } + + template + void write7BitEncoded(T value) + { + do + { + unsigned char c = (unsigned char) (value & 0x7F); + value >>= 7; + if (value) c |= 0x80; + _ostr.write((const char*) &c, 1); + } + while (value); + } + + BinaryWriter& write(const char* value, std::size_t length); + std::ostream& _ostr; bool _flipBytes; TextConverter* _pTextConverter; diff --git a/Foundation/include/Poco/ByteOrder.h b/Foundation/include/Poco/ByteOrder.h index 78022f760..4fa0e4fbb 100644 --- a/Foundation/include/Poco/ByteOrder.h +++ b/Foundation/include/Poco/ByteOrder.h @@ -24,7 +24,6 @@ #include // builtins #endif - namespace Poco { @@ -38,6 +37,8 @@ public: static UInt16 flipBytes(UInt16 value); static Int32 flipBytes(Int32 value); static UInt32 flipBytes(UInt32 value); + static float flipBytes(float value); + static double flipBytes(double value); #if defined(POCO_HAVE_INT64) static Int64 flipBytes(Int64 value); static UInt64 flipBytes(UInt64 value); @@ -96,6 +97,21 @@ public: static Int64 fromNetwork(Int64 value); static UInt64 fromNetwork (UInt64 value); #endif + +private: + template + static T flip(T value) + { + T flip = value; + std::size_t halfSize = sizeof(T) / 2; + char* flipP = reinterpret_cast(&flip); + + for (std::size_t i = 0; i < halfSize; i++) + { + std::swap(flipP[i], flipP[sizeof(T) - i - 1]); + } + return flip; + } }; @@ -152,6 +168,18 @@ inline Int32 ByteOrder::flipBytes(Int32 value) } +inline float ByteOrder::flipBytes(float value) +{ + return flip(value); +} + + +inline double ByteOrder::flipBytes(double value) +{ + return flip(value); +} + + #if defined(POCO_HAVE_INT64) inline UInt64 ByteOrder::flipBytes(UInt64 value) { diff --git a/Foundation/src/BinaryReader.cpp b/Foundation/src/BinaryReader.cpp index b3095df5e..ab4bb2652 100644 --- a/Foundation/src/BinaryReader.cpp +++ b/Foundation/src/BinaryReader.cpp @@ -15,7 +15,6 @@ #include "Poco/BinaryReader.h" -#include "Poco/ByteOrder.h" #include "Poco/TextEncoding.h" #include "Poco/TextConverter.h" #include @@ -56,119 +55,81 @@ BinaryReader::~BinaryReader() BinaryReader& BinaryReader::operator >> (bool& value) { - _istr.read((char*) &value, sizeof(value)); - return *this; + return read(value, false); } BinaryReader& BinaryReader::operator >> (char& value) { - _istr.read((char*) &value, sizeof(value)); - return *this; + return read(value, false); } BinaryReader& BinaryReader::operator >> (unsigned char& value) { - _istr.read((char*) &value, sizeof(value)); - return *this; + return read(value, false); } BinaryReader& BinaryReader::operator >> (signed char& value) { - _istr.read((char*) &value, sizeof(value)); - return *this; + return read(value, false); } BinaryReader& BinaryReader::operator >> (short& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (unsigned short& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (int& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (unsigned int& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (long& value) { - _istr.read((char*) &value, sizeof(value)); #if defined(POCO_LONG_IS_64_BIT) - if (_flipBytes) value = ByteOrder::flipBytes((Int64) value); + return read((Int64&) value, _flipBytes); #else - if (_flipBytes) value = ByteOrder::flipBytes((Int32) value); + return read((Int32&) value, _flipBytes); #endif - return *this; } BinaryReader& BinaryReader::operator >> (unsigned long& value) { - _istr.read((char*) &value, sizeof(value)); #if defined(POCO_LONG_IS_64_BIT) - if (_flipBytes) value = ByteOrder::flipBytes((UInt64) value); + return read((UInt64&) value, _flipBytes); #else - if (_flipBytes) value = ByteOrder::flipBytes((UInt32) value); + return read((UInt32&) value, _flipBytes); #endif - return *this; } BinaryReader& BinaryReader::operator >> (float& value) { - if (_flipBytes) - { - char* ptr = (char*) &value; - ptr += sizeof(value); - for (unsigned i = 0; i < sizeof(value); ++i) - _istr.read(--ptr, 1); - } - else - { - _istr.read((char*) &value, sizeof(value)); - } - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (double& value) { - if (_flipBytes) - { - char* ptr = (char*) &value; - ptr += sizeof(value); - for (unsigned i = 0; i < sizeof(value); ++i) - _istr.read(--ptr, 1); - } - else - { - _istr.read((char*) &value, sizeof(value)); - } - return *this; + return read(value, _flipBytes); } @@ -177,17 +138,13 @@ BinaryReader& BinaryReader::operator >> (double& value) BinaryReader& BinaryReader::operator >> (Int64& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } BinaryReader& BinaryReader::operator >> (UInt64& value) { - _istr.read((char*) &value, sizeof(value)); - if (_flipBytes) value = ByteOrder::flipBytes(value); - return *this; + return read(value, _flipBytes); } @@ -196,17 +153,11 @@ BinaryReader& BinaryReader::operator >> (UInt64& value) BinaryReader& BinaryReader::operator >> (std::string& value) { + if (!_istr.good()) return *this; + UInt32 size = 0; read7BitEncoded(size); - value.clear(); - if (!_istr.good()) return *this; - value.reserve(size); - while (size--) - { - char c; - if (!_istr.read(&c, 1).good()) break; - value += c; - } + readRaw(size, value); if (_pTextConverter) { std::string converted; @@ -219,19 +170,7 @@ BinaryReader& BinaryReader::operator >> (std::string& value) void BinaryReader::read7BitEncoded(UInt32& value) { - char c; - value = 0; - int s = 0; - do - { - c = 0; - _istr.read(&c, 1); - UInt32 x = (c & 0x7F); - x <<= s; - value += x; - s += 7; - } - while (c & 0x80); + read7BitEncoded(value); } @@ -240,19 +179,7 @@ void BinaryReader::read7BitEncoded(UInt32& value) void BinaryReader::read7BitEncoded(UInt64& value) { - char c; - value = 0; - int s = 0; - do - { - c = 0; - _istr.read(&c, 1); - UInt64 x = (c & 0x7F); - x <<= s; - value += x; - s += 7; - } - while (c & 0x80); + read7BitEncoded(value); } diff --git a/Foundation/src/BinaryWriter.cpp b/Foundation/src/BinaryWriter.cpp index 35c85cc0c..ce5fcab74 100644 --- a/Foundation/src/BinaryWriter.cpp +++ b/Foundation/src/BinaryWriter.cpp @@ -15,7 +15,6 @@ #include "Poco/BinaryWriter.h" -#include "Poco/ByteOrder.h" #include "Poco/TextEncoding.h" #include "Poco/TextConverter.h" #include @@ -56,161 +55,81 @@ BinaryWriter::~BinaryWriter() BinaryWriter& BinaryWriter::operator << (bool value) { - _ostr.write((const char*) &value, sizeof(value)); - return *this; + return write(value, false); } BinaryWriter& BinaryWriter::operator << (char value) { - _ostr.write((const char*) &value, sizeof(value)); - return *this; + return write(value, false); } BinaryWriter& BinaryWriter::operator << (unsigned char value) { - _ostr.write((const char*) &value, sizeof(value)); - return *this; + return write(value, false); } BinaryWriter& BinaryWriter::operator << (signed char value) { - _ostr.write((const char*) &value, sizeof(value)); - return *this; + return write(value, false); } BinaryWriter& BinaryWriter::operator << (short value) { - if (_flipBytes) - { - short fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (unsigned short value) { - if (_flipBytes) - { - unsigned short fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (int value) { - if (_flipBytes) - { - int fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (unsigned int value) { - if (_flipBytes) - { - unsigned int fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (long value) { - if (_flipBytes) - { #if defined(POCO_LONG_IS_64_BIT) - long fValue = ByteOrder::flipBytes((Int64) value); + return write((Int64) value, _flipBytes); #else - long fValue = ByteOrder::flipBytes((Int32) value); + return write((Int32) value, _flipBytes); #endif - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; } BinaryWriter& BinaryWriter::operator << (unsigned long value) { - if (_flipBytes) - { #if defined(POCO_LONG_IS_64_BIT) - long fValue = ByteOrder::flipBytes((UInt64) value); + return write((UInt64) value, _flipBytes); #else - long fValue = ByteOrder::flipBytes((UInt32) value); + return write((UInt32) value, _flipBytes); #endif - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; } BinaryWriter& BinaryWriter::operator << (float value) { - if (_flipBytes) - { - const char* ptr = (const char*) &value; - ptr += sizeof(value); - for (unsigned i = 0; i < sizeof(value); ++i) - _ostr.write(--ptr, 1); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (double value) { - if (_flipBytes) - { - const char* ptr = (const char*) &value; - ptr += sizeof(value); - for (unsigned i = 0; i < sizeof(value); ++i) - _ostr.write(--ptr, 1); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } @@ -219,31 +138,13 @@ BinaryWriter& BinaryWriter::operator << (double value) BinaryWriter& BinaryWriter::operator << (Int64 value) { - if (_flipBytes) - { - Int64 fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } BinaryWriter& BinaryWriter::operator << (UInt64 value) { - if (_flipBytes) - { - UInt64 fValue = ByteOrder::flipBytes(value); - _ostr.write((const char*) &fValue, sizeof(fValue)); - } - else - { - _ostr.write((const char*) &value, sizeof(value)); - } - return *this; + return write(value, _flipBytes); } @@ -252,56 +153,19 @@ BinaryWriter& BinaryWriter::operator << (UInt64 value) BinaryWriter& BinaryWriter::operator << (const std::string& value) { - if (_pTextConverter) - { - std::string converted; - _pTextConverter->convert(value, converted); - UInt32 length = (UInt32) converted.size(); - write7BitEncoded(length); - _ostr.write(converted.data(), length); - } - else - { - UInt32 length = (UInt32) value.size(); - write7BitEncoded(length); - _ostr.write(value.data(), length); - } - return *this; + return write(value.c_str(), value.length()); } BinaryWriter& BinaryWriter::operator << (const char* value) { - poco_check_ptr (value); - - if (_pTextConverter) - { - std::string converted; - _pTextConverter->convert(value, static_cast(std::strlen(value)), converted); - UInt32 length = (UInt32) converted.size(); - write7BitEncoded(length); - _ostr.write(converted.data(), length); - } - else - { - UInt32 length = static_cast(std::strlen(value)); - write7BitEncoded(length); - _ostr.write(value, length); - } - return *this; + return write(value, std::strlen(value)); } void BinaryWriter::write7BitEncoded(UInt32 value) { - do - { - unsigned char c = (unsigned char) (value & 0x7F); - value >>= 7; - if (value) c |= 0x80; - _ostr.write((const char*) &c, 1); - } - while (value); + write7BitEncoded(value); } @@ -310,14 +174,7 @@ void BinaryWriter::write7BitEncoded(UInt32 value) void BinaryWriter::write7BitEncoded(UInt64 value) { - do - { - unsigned char c = (unsigned char) (value & 0x7F); - value >>= 7; - if (value) c |= 0x80; - _ostr.write((const char*) &c, 1); - } - while (value); + write7BitEncoded(value); } @@ -350,4 +207,26 @@ void BinaryWriter::flush() } +BinaryWriter& BinaryWriter::write(const char* value, std::size_t length) +{ + poco_check_ptr (value); + + if (_pTextConverter) + { + std::string converted; + _pTextConverter->convert(value, static_cast(length), converted); + UInt32 convertedLength = (UInt32) converted.length(); + write7BitEncoded(convertedLength); + _ostr.write(converted.data(), convertedLength); + } + else + { + UInt32 lengthUInt32 = static_cast(length); + write7BitEncoded(lengthUInt32); + _ostr.write(value, lengthUInt32); + } + return *this; +} + + } // namespace Poco diff --git a/Foundation/testsuite/src/ByteOrderTest.cpp b/Foundation/testsuite/src/ByteOrderTest.cpp index 7f829910b..d2e16bd32 100644 --- a/Foundation/testsuite/src/ByteOrderTest.cpp +++ b/Foundation/testsuite/src/ByteOrderTest.cpp @@ -67,6 +67,46 @@ void ByteOrderTest::testByteOrderFlip() flip = ByteOrder::flipBytes(flip); assert (flip == norm); } + { + unsigned char c = 0x00; + float norm = 0; + unsigned char* normP = reinterpret_cast(&norm); + for (unsigned i = 0; i < sizeof(float); i++) + { + normP[i] |= c; + c += 0x11; + } + + float flip = ByteOrder::flipBytes(norm); + unsigned char* flipP = reinterpret_cast(&flip); + for (unsigned i = 0; i < sizeof(float); i++) + { + assert(normP[i] == flipP[sizeof(float) - 1 - i]); + } + + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } + { + unsigned char c = 0x00; + double norm = 0; + unsigned char* normP = reinterpret_cast(&norm); + for (unsigned i = 0; i < sizeof(double); i++) + { + normP[i] |= c; + c += 0x11; + } + + double flip = ByteOrder::flipBytes(norm); + unsigned char* flipP = reinterpret_cast(&flip); + for (unsigned i = 0; i < sizeof(double); i++) + { + assert(normP[i] == flipP[sizeof(double) - 1 - i]); + } + + flip = ByteOrder::flipBytes(flip); + assert (flip == norm); + } #if defined(POCO_HAVE_INT64) { Int64 norm = (Int64(0x8899AABB) << 32) + 0xCCDDEEFF;