#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_STORAGE_SOURCE 1 #include "Nuclex/Storage/Binary/BinaryBlobWriter.h" #include "Nuclex/Storage/Blob.h" #include "../Helpers/EndianFlip.h" namespace { // ------------------------------------------------------------------------------------------- // /// Union of a 32 bit integer and a 32 bit single precision float union IntegerFloatUnion { /// Value in floating point format public: float FloatValue; /// Value in integer format public: std::uint32_t IntegerValue; }; // ------------------------------------------------------------------------------------------- // /// Union of a 64 bit integer and a 64 bit double precision float union IntegerDoubleUnion { /// Value in double precision floating point format public: double DoubleValue; /// Value in integer format public: std::uint64_t IntegerValue; }; // ------------------------------------------------------------------------------------------- // } // anonymous namespace namespace Nuclex { namespace Storage { namespace Binary { // ------------------------------------------------------------------------------------------- // BinaryBlobWriter::BinaryBlobWriter(const std::shared_ptr &blob) : blob(blob), position(0), flipBytes(false) {} // ------------------------------------------------------------------------------------------- // bool BinaryBlobWriter::IsLittleEndian() const { #if defined(NUCLEX_STORAGE_BIG_ENDIAN) // On a big endian system, we're in little endian mode if we flip return this->flipBytes; #else // On a little endian system, we're in little endian mode by default return !this->flipBytes; #endif } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::SetLittleEndian(bool useLittleEndian /* = true */) { #if defined(NUCLEX_STORAGE_BIG_ENDIAN) // Big endian requires us to flip if the file should be little endian this->flipBytes = useLittleEndian; #else // Little endian requires no operation if the file should be little endian this->flipBytes = !useLittleEndian; #endif } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(bool value) { std::uint8_t flag = value ? 1 : 0; this->blob->WriteAt(this->position, &flag, sizeof(flag)); this->position += sizeof(flag); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::uint8_t value) { this->blob->WriteAt(this->position, &value, sizeof(value)); this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::int8_t value) { this->blob->WriteAt(this->position, &value, sizeof(value)); this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::uint16_t value) { if(this->flipBytes) { std::uint16_t temp = Helpers::EndianFlip(value); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::int16_t value) { if(this->flipBytes) { std::uint16_t temp = Helpers::EndianFlip(static_cast(value)); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::uint32_t value) { if(this->flipBytes) { std::uint32_t temp = Helpers::EndianFlip(value); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::int32_t value) { if(this->flipBytes) { std::uint32_t temp = Helpers::EndianFlip(static_cast(value)); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::uint64_t value) { if(this->flipBytes) { std::uint64_t temp = Helpers::EndianFlip(value); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(std::int64_t value) { if(this->flipBytes) { std::uint64_t temp = Helpers::EndianFlip(static_cast(value)); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(float value) { if(this->flipBytes) { IntegerFloatUnion temp; temp.FloatValue = value; temp.IntegerValue = Helpers::EndianFlip(temp.IntegerValue); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(double value) { if(this->flipBytes) { IntegerDoubleUnion temp; temp.DoubleValue = value; temp.IntegerValue = Helpers::EndianFlip(temp.IntegerValue); this->blob->WriteAt(this->position, &temp, sizeof(temp)); } else { this->blob->WriteAt(this->position, &value, sizeof(value)); } this->position += sizeof(value); } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(const std::string &value) { std::uint32_t length = static_cast(value.length()); Write(length); if(length > 0) { Write(value.c_str(), length * sizeof(char)); } } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(const std::wstring &value) { std::uint32_t length = static_cast(value.length()); Write(length); if(length > 0) { Write(value.c_str(), length * sizeof(wchar_t)); } } // ------------------------------------------------------------------------------------------- // void BinaryBlobWriter::Write(const void *buffer, std::size_t byteCount) { this->blob->WriteAt(this->position, buffer, byteCount); this->position += byteCount; } // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Storage::Binary