From e59d770ee0e66bc54b4ac7e51516a025214c3db4 Mon Sep 17 00:00:00 2001 From: Lexi Mayfield Date: Sun, 3 Mar 2024 17:08:06 -0500 Subject: [PATCH] Convert all float serialization --- include/lexio/serialize/float.hpp | 108 +++++++++------ include/lexio/serialize/tryfloat.hpp | 192 +++++++++------------------ include/lexio/try.hpp | 9 ++ 3 files changed, 141 insertions(+), 168 deletions(-) diff --git a/include/lexio/serialize/float.hpp b/include/lexio/serialize/float.hpp index 3c157d2..1c0edbf 100644 --- a/include/lexio/serialize/float.hpp +++ b/include/lexio/serialize/float.hpp @@ -36,12 +36,15 @@ namespace LexIO */ inline float32_t ReadFloat32LE(const ReaderRef &reader) { - float32_t rvo; - if (!TryReadFloat32LE(rvo, reader)) - { - throw std::runtime_error("could not read"); - } - return rvo; + float32_t out = 0; + uint8_t buf[sizeof(uint32_t)] = {0}; + ReadExact(buf, reader); + + uint32_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_BE_BSWAP32(bits); + std::memcpy(&out, &bits, sizeof(out)); + return out; } /** @@ -53,12 +56,15 @@ inline float32_t ReadFloat32LE(const ReaderRef &reader) */ inline float32_t ReadFloat32BE(const ReaderRef &reader) { - float32_t rvo; - if (!TryReadFloat32BE(rvo, reader)) - { - throw std::runtime_error("could not read"); - } - return rvo; + float32_t out = 0; + uint8_t buf[sizeof(uint32_t)] = {0}; + ReadExact(buf, reader); + + uint32_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_LE_BSWAP32(bits); + std::memcpy(&out, &bits, sizeof(out)); + return out; } /** @@ -70,10 +76,14 @@ inline float32_t ReadFloat32BE(const ReaderRef &reader) */ inline void WriteFloat32LE(const WriterRef &writer, float32_t value) { - if (!TryWriteFloat32LE(writer, value)) - { - throw std::runtime_error("could not write"); - } + uint32_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); + + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_BE_BSWAP32(bits); + std::memcpy(buf, &bits, sizeof(buf)); + + WriteExact(writer, buf, sizeof(buf)); } /** @@ -85,10 +95,14 @@ inline void WriteFloat32LE(const WriterRef &writer, float32_t value) */ inline void WriteFloat32BE(const WriterRef &writer, float32_t value) { - if (!TryWriteFloat32BE(writer, value)) - { - throw std::runtime_error("could not write"); - } + uint32_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); + + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_LE_BSWAP32(bits); + std::memcpy(buf, &bits, sizeof(buf)); + + WriteExact(writer, buf, sizeof(buf)); } //****************************************************************************** @@ -102,12 +116,15 @@ inline void WriteFloat32BE(const WriterRef &writer, float32_t value) */ inline float64_t ReadFloat64LE(const ReaderRef &reader) { - float64_t rvo; - if (!TryReadFloat64LE(rvo, reader)) - { - throw std::runtime_error("could not read"); - } - return rvo; + float64_t out = 0; + uint8_t buf[sizeof(uint64_t)] = {0}; + ReadExact(buf, reader); + + uint64_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_BE_BSWAP64(bits); + std::memcpy(&out, &bits, sizeof(out)); + return out; } /** @@ -119,12 +136,15 @@ inline float64_t ReadFloat64LE(const ReaderRef &reader) */ inline float64_t ReadFloat64BE(const ReaderRef &reader) { - float64_t rvo; - if (!TryReadFloat64BE(rvo, reader)) - { - throw std::runtime_error("could not read"); - } - return rvo; + float64_t out = 0; + uint8_t buf[sizeof(uint64_t)] = {0}; + ReadExact(buf, reader); + + uint64_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_LE_BSWAP64(bits); + std::memcpy(&out, &bits, sizeof(out)); + return out; } /** @@ -136,10 +156,14 @@ inline float64_t ReadFloat64BE(const ReaderRef &reader) */ inline void WriteFloat64LE(const WriterRef &writer, float64_t value) { - if (!TryWriteFloat64LE(writer, value)) - { - throw std::runtime_error("could not write"); - } + uint64_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); + + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_BE_BSWAP64(bits); + std::memcpy(buf, &bits, sizeof(buf)); + + WriteExact(writer, buf, sizeof(buf)); } /** @@ -151,10 +175,14 @@ inline void WriteFloat64LE(const WriterRef &writer, float64_t value) */ inline void WriteFloat64BE(const WriterRef &writer, float64_t value) { - if (!TryWriteFloat64BE(writer, value)) - { - throw std::runtime_error("could not write"); - } + uint64_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); + + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_LE_BSWAP64(bits); + std::memcpy(buf, &bits, sizeof(buf)); + + return WriteExact(writer, buf, sizeof(buf)); } } // namespace LexIO diff --git a/include/lexio/serialize/tryfloat.hpp b/include/lexio/serialize/tryfloat.hpp index 873760e..fdb9ccd 100644 --- a/include/lexio/serialize/tryfloat.hpp +++ b/include/lexio/serialize/tryfloat.hpp @@ -36,27 +36,19 @@ using float64_t = double; * @param reader Reader to read from. * @return True if the read was successful. */ -inline bool TryReadFloat32LE(float32_t &out, const ReaderRef &reader) +inline bool TryReadFloat32LE(float32_t &out, const ReaderRef &reader) noexcept { - try - { - uint8_t buf[sizeof(uint32_t)] = {0}; - const size_t count = Read(buf, reader); - if (count != sizeof(buf)) - { - return false; - } - - uint32_t bits = 0; - std::memcpy(&bits, buf, sizeof(bits)); - bits = LEXIO_IF_BE_BSWAP32(bits); - std::memcpy(&out, &bits, sizeof(out)); - return true; - } - catch (std::runtime_error &) + uint8_t buf[sizeof(uint32_t)] = {0}; + if (!TryReadExact(buf, reader)) { return false; } + + uint32_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_BE_BSWAP32(bits); + std::memcpy(&out, &bits, sizeof(out)); + return true; } /** @@ -66,27 +58,19 @@ inline bool TryReadFloat32LE(float32_t &out, const ReaderRef &reader) * @param reader Reader to read from. * @return True if the read was successful. */ -inline bool TryReadFloat32BE(float32_t &out, const ReaderRef &reader) +inline bool TryReadFloat32BE(float32_t &out, const ReaderRef &reader) noexcept { - try - { - uint8_t buf[sizeof(uint32_t)] = {0}; - const size_t count = Read(buf, reader); - if (count != sizeof(buf)) - { - return false; - } - - uint32_t bits = 0; - std::memcpy(&bits, buf, sizeof(bits)); - bits = LEXIO_IF_LE_BSWAP32(bits); - std::memcpy(&out, &bits, sizeof(out)); - return true; - } - catch (std::runtime_error &) + uint8_t buf[sizeof(uint32_t)] = {0}; + if (!TryReadExact(buf, reader)) { return false; } + + uint32_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_LE_BSWAP32(bits); + std::memcpy(&out, &bits, sizeof(out)); + return true; } /** @@ -96,24 +80,16 @@ inline bool TryReadFloat32BE(float32_t &out, const ReaderRef &reader) * @param value Integer to write. * @return True if the write was successful. */ -inline bool TryWriteFloat32LE(const WriterRef &writer, float32_t value) +inline bool TryWriteFloat32LE(const WriterRef &writer, float32_t value) noexcept { - try - { - uint32_t bits = 0; - std::memcpy(&bits, &value, sizeof(bits)); + uint32_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); - uint8_t buf[sizeof(bits)] = {0}; - bits = LEXIO_IF_BE_BSWAP32(bits); - std::memcpy(buf, &bits, sizeof(buf)); + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_BE_BSWAP32(bits); + std::memcpy(buf, &bits, sizeof(buf)); - const size_t count = Write(writer, buf, sizeof(buf)); - return count == sizeof(buf); - } - catch (std::runtime_error &) - { - return false; - } + return TryWriteExact(writer, buf, sizeof(buf)); } /** @@ -123,24 +99,16 @@ inline bool TryWriteFloat32LE(const WriterRef &writer, float32_t value) * @param value Integer to write. * @return True if the write was successful. */ -inline bool TryWriteFloat32BE(const WriterRef &writer, float32_t value) +inline bool TryWriteFloat32BE(const WriterRef &writer, float32_t value) noexcept { - try - { - uint32_t bits = 0; - std::memcpy(&bits, &value, sizeof(bits)); + uint32_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); - uint8_t buf[sizeof(bits)] = {0}; - bits = LEXIO_IF_LE_BSWAP32(bits); - std::memcpy(buf, &bits, sizeof(buf)); + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_LE_BSWAP32(bits); + std::memcpy(buf, &bits, sizeof(buf)); - const size_t count = Write(writer, buf, sizeof(buf)); - return count == sizeof(buf); - } - catch (std::runtime_error &) - { - return false; - } + return TryWriteExact(writer, buf, sizeof(buf)); } //****************************************************************************** @@ -152,27 +120,19 @@ inline bool TryWriteFloat32BE(const WriterRef &writer, float32_t value) * @param reader Reader to read from. * @return True if the read was successful. */ -inline bool TryReadFloat64LE(float64_t &out, const ReaderRef &reader) +inline bool TryReadFloat64LE(float64_t &out, const ReaderRef &reader) noexcept { - try - { - uint8_t buf[sizeof(uint64_t)] = {0}; - const size_t count = Read(buf, reader); - if (count != sizeof(buf)) - { - return false; - } - - uint64_t bits = 0; - std::memcpy(&bits, buf, sizeof(bits)); - bits = LEXIO_IF_BE_BSWAP64(bits); - std::memcpy(&out, &bits, sizeof(out)); - return true; - } - catch (std::runtime_error &) + uint8_t buf[sizeof(uint64_t)] = {0}; + if (!TryReadExact(buf, reader)) { return false; } + + uint64_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_BE_BSWAP64(bits); + std::memcpy(&out, &bits, sizeof(out)); + return true; } /** @@ -182,27 +142,19 @@ inline bool TryReadFloat64LE(float64_t &out, const ReaderRef &reader) * @param reader Reader to read from. * @return True if the read was successful. */ -inline bool TryReadFloat64BE(float64_t &out, const ReaderRef &reader) +inline bool TryReadFloat64BE(float64_t &out, const ReaderRef &reader) noexcept { - try - { - uint8_t buf[sizeof(uint64_t)] = {0}; - const size_t count = Read(buf, reader); - if (count != sizeof(buf)) - { - return false; - } - - uint64_t bits = 0; - std::memcpy(&bits, buf, sizeof(bits)); - bits = LEXIO_IF_LE_BSWAP64(bits); - std::memcpy(&out, &bits, sizeof(out)); - return true; - } - catch (std::runtime_error &) + uint8_t buf[sizeof(uint64_t)] = {0}; + if (!TryReadExact(buf, reader)) { return false; } + + uint64_t bits = 0; + std::memcpy(&bits, buf, sizeof(bits)); + bits = LEXIO_IF_LE_BSWAP64(bits); + std::memcpy(&out, &bits, sizeof(out)); + return true; } /** @@ -212,24 +164,16 @@ inline bool TryReadFloat64BE(float64_t &out, const ReaderRef &reader) * @param value Integer to write. * @return True if the write was successful. */ -inline bool TryWriteFloat64LE(const WriterRef &writer, float64_t value) +inline bool TryWriteFloat64LE(const WriterRef &writer, float64_t value) noexcept { - try - { - uint64_t bits = 0; - std::memcpy(&bits, &value, sizeof(bits)); + uint64_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); - uint8_t buf[sizeof(bits)] = {0}; - bits = LEXIO_IF_BE_BSWAP64(bits); - std::memcpy(buf, &bits, sizeof(buf)); + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_BE_BSWAP64(bits); + std::memcpy(buf, &bits, sizeof(buf)); - const size_t count = Write(writer, buf, sizeof(buf)); - return count == sizeof(buf); - } - catch (std::runtime_error &) - { - return false; - } + return TryWriteExact(writer, buf, sizeof(buf)); } /** @@ -239,24 +183,16 @@ inline bool TryWriteFloat64LE(const WriterRef &writer, float64_t value) * @param value Integer to write. * @return True if the write was successful. */ -inline bool TryWriteFloat64BE(const WriterRef &writer, float64_t value) +inline bool TryWriteFloat64BE(const WriterRef &writer, float64_t value) noexcept { - try - { - uint64_t bits = 0; - std::memcpy(&bits, &value, sizeof(bits)); + uint64_t bits = 0; + std::memcpy(&bits, &value, sizeof(bits)); - uint8_t buf[sizeof(bits)] = {0}; - bits = LEXIO_IF_LE_BSWAP64(bits); - std::memcpy(buf, &bits, sizeof(buf)); + uint8_t buf[sizeof(bits)] = {0}; + bits = LEXIO_IF_LE_BSWAP64(bits); + std::memcpy(buf, &bits, sizeof(buf)); - const size_t count = Write(writer, buf, sizeof(buf)); - return count == sizeof(buf); - } - catch (std::runtime_error &) - { - return false; - } + return TryWriteExact(writer, buf, sizeof(buf)); } } // namespace LexIO diff --git a/include/lexio/try.hpp b/include/lexio/try.hpp index 0c911fc..3198e85 100644 --- a/include/lexio/try.hpp +++ b/include/lexio/try.hpp @@ -16,6 +16,15 @@ #pragma once +/** + * @file core.hpp + * @brief Core interfaces and functions implemented without exceptions. + * + * Since LexIO traits use exceptions, we store the exception in a thread-local + * global. Ideally, we would use , but supporting C++14 means no + * std::expected or even std::variant without a third-party implementation. + */ + #include "./core.hpp" #include