#ifndef MONOFORMAT_PARSEHELPERS_HPP #define MONOFORMAT_PARSEHELPERS_HPP #include #include #include #include #include // for std::ignore namespace monoformat { enum class ParseError { BufferSizeMismatch = 1, InvalidValue = 2, }; inline std::expected peekU8LE(std::span buffer) { if (buffer.size() < 1) { return std::unexpected(ParseError::BufferSizeMismatch); } return static_cast(buffer[0]); } inline std::expected readU8LE(std::span& buffer) { auto result = peekU8LE(buffer); if (result) { buffer = buffer.subspan(1); } return result; } inline std::expected peekU8BE(std::span buffer) { if (buffer.size() < 1) { return std::unexpected(ParseError::BufferSizeMismatch); } return static_cast(buffer[0]); } inline std::expected readU8BE(std::span& buffer) { auto result = peekU8BE(buffer); if (result) { buffer = buffer.subspan(1); } return result; } inline std::expected peekU16LE(std::span buffer) { if (buffer.size() < 2) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[0]) << 0u) | (static_cast(buffer[1]) << 8u); } inline std::expected readU16LE(std::span& buffer) { auto result = peekU16LE(buffer); if (result) { buffer = buffer.subspan(2); } return result; } inline std::expected peekU16BE(std::span buffer) { if (buffer.size() < 2) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[1]) << 0u) | (static_cast(buffer[0]) << 8u); } inline std::expected readU16BE(std::span& buffer) { auto result = peekU16BE(buffer); if (result) { buffer = buffer.subspan(2); } return result; } inline std::expected peekU24LE(std::span buffer) { if (buffer.size() < 3) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[0]) << 0u) | (static_cast(buffer[1]) << 8u) | (static_cast(buffer[2]) << 16u); } inline std::expected readU24LE(std::span& buffer) { auto result = peekU24LE(buffer); if (result) { buffer = buffer.subspan(3); } return result; } inline std::expected peekU24BE(std::span buffer) { if (buffer.size() < 3) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[2]) << 0u) | (static_cast(buffer[1]) << 8u) | (static_cast(buffer[0]) << 16u); } inline std::expected readU24BE(std::span& buffer) { auto result = peekU24BE(buffer); if (result) { buffer = buffer.subspan(3); } return result; } inline std::expected peekU32LE(std::span buffer) { if (buffer.size() < 4) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[0]) << 0u) | (static_cast(buffer[1]) << 8u) | (static_cast(buffer[2]) << 16u) | (static_cast(buffer[3]) << 24u); } inline std::expected readU32LE(std::span& buffer) { auto result = peekU32LE(buffer); if (result) { buffer = buffer.subspan(4); } return result; } inline std::expected peekU32BE(std::span buffer) { if (buffer.size() < 4) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[3]) << 0u) | (static_cast(buffer[2]) << 8u) | (static_cast(buffer[1]) << 16u) | (static_cast(buffer[0]) << 24u); } inline std::expected readU32BE(std::span& buffer) { auto result = peekU32BE(buffer); if (result) { buffer = buffer.subspan(8); } return result; } inline std::expected peekU64LE(std::span buffer) { if (buffer.size() < 8) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[0]) << 0u) | (static_cast(buffer[1]) << 8u) | (static_cast(buffer[2]) << 16u) | (static_cast(buffer[3]) << 24u) | (static_cast(buffer[4]) << 32u) | (static_cast(buffer[5]) << 40u) | (static_cast(buffer[6]) << 48u) | (static_cast(buffer[7]) << 56u); } inline std::expected readU64LE(std::span& buffer) { auto result = peekU64LE(buffer); if (result) { buffer = buffer.subspan(8); } return result; } inline std::expected peekU64BE(std::span buffer) { if (buffer.size() < 8) { return std::unexpected(ParseError::BufferSizeMismatch); } return (static_cast(buffer[7]) << 0u) | (static_cast(buffer[6]) << 8u) | (static_cast(buffer[5]) << 16u) | (static_cast(buffer[4]) << 24u) | (static_cast(buffer[3]) << 32u) | (static_cast(buffer[2]) << 40u) | (static_cast(buffer[1]) << 48u) | (static_cast(buffer[0]) << 56u); } inline std::expected readU64BE(std::span& buffer) { auto result = peekU64BE(buffer); if (result) { buffer = buffer.subspan(8); } return result; } inline std::expected, ParseError> peekBuffer(std::span buffer, std::size_t n) { if (buffer.size() < n) { return std::unexpected(ParseError::BufferSizeMismatch); } return buffer.subspan(0, n); } inline std::expected, ParseError> readBuffer(std::span& buffer, std::size_t n) { auto result = peekBuffer(buffer, n); if (result) { buffer = buffer.subspan(n); } return result; } inline std::expected expectEnd(std::span buffer) { if (buffer.size() > 0) { return std::unexpected(ParseError::BufferSizeMismatch); } return {}; } inline std::pair overflowingShr(std::uint8_t value, std::uint8_t bits) { bool overflow = false; if (bits >= 8) { bits = bits & 0x07; overflow = true; } return {value >> bits, overflow}; } inline std::pair overflowingShl(std::uint8_t value, std::uint8_t bits) { bool overflow = false; if (bits >= 8) { bits = bits & 0x07; overflow = true; } return {value << bits, overflow}; } inline std::size_t writeU8LE(std::span& target, std::size_t pos, std::uint8_t value) { if (pos < target.size()) { target[pos] = static_cast(value); } return pos + 1; } inline std::size_t writeU8BE(std::span& target, std::size_t pos, std::uint8_t value) { if (pos < target.size()) { target[pos] = static_cast(value); } return pos + 1; } inline std::size_t writeU16LE(std::span& target, std::size_t pos, std::uint16_t value) { if ((pos + 1) < target.size()) { target[pos + 0] = static_cast((value >> 0u) & 0xffu); target[pos + 1] = static_cast((value >> 8u) & 0xffu); } return pos + 2; } inline std::size_t writeU16BE(std::span& target, std::size_t pos, std::uint16_t value) { if ((pos + 1) < target.size()) { target[pos + 0] = static_cast((value >> 8u) & 0xffu); target[pos + 1] = static_cast((value >> 0u) & 0xffu); } return pos + 2; } inline std::size_t writeU24LE(std::span& target, std::size_t pos, std::uint32_t value) { if ((pos + 2) < target.size()) { target[pos + 0] = static_cast((value >> 0u) & 0xffu); target[pos + 1] = static_cast((value >> 8u) & 0xffu); target[pos + 2] = static_cast((value >> 16u) & 0xffu); } return pos + 3; } inline std::size_t writeU24BE(std::span& target, std::size_t pos, std::uint32_t value) { if ((pos + 2) < target.size()) { target[pos + 0] = static_cast((value >> 16u) & 0xffu); target[pos + 1] = static_cast((value >> 8u) & 0xffu); target[pos + 2] = static_cast((value >> 0u) & 0xffu); } return pos + 3; } inline std::size_t writeU32LE(std::span& target, std::size_t pos, std::uint32_t value) { if ((pos + 3) < target.size()) { target[pos + 0] = static_cast((value >> 0u) & 0xffu); target[pos + 1] = static_cast((value >> 8u) & 0xffu); target[pos + 2] = static_cast((value >> 16u) & 0xffu); target[pos + 3] = static_cast((value >> 24u) & 0xffu); } return pos + 4; } inline std::size_t writeU32BE(std::span& target, std::size_t pos, std::uint32_t value) { if ((pos + 3) < target.size()) { target[pos + 0] = static_cast((value >> 24u) & 0xffu); target[pos + 1] = static_cast((value >> 16u) & 0xffu); target[pos + 2] = static_cast((value >> 8u) & 0xffu); target[pos + 3] = static_cast((value >> 0u) & 0xffu); } return pos + 4; } inline std::size_t writeU64LE(std::span& target, std::size_t pos, std::uint64_t value) { if ((pos + 7) < target.size()) { target[pos + 0] = static_cast((value >> 0u) & 0xffu); target[pos + 1] = static_cast((value >> 8u) & 0xffu); target[pos + 2] = static_cast((value >> 16u) & 0xffu); target[pos + 3] = static_cast((value >> 24u) & 0xffu); target[pos + 4] = static_cast((value >> 32u) & 0xffu); target[pos + 5] = static_cast((value >> 40u) & 0xffu); target[pos + 6] = static_cast((value >> 48u) & 0xffu); target[pos + 7] = static_cast((value >> 56u) & 0xffu); } return pos + 8; } inline std::size_t writeU64BE(std::span& target, std::size_t pos, std::uint64_t value) { if ((pos + 3) < target.size()) { target[pos + 0] = static_cast((value >> 56u) & 0xffu); target[pos + 1] = static_cast((value >> 48u) & 0xffu); target[pos + 2] = static_cast((value >> 40u) & 0xffu); target[pos + 3] = static_cast((value >> 32u) & 0xffu); target[pos + 4] = static_cast((value >> 24u) & 0xffu); target[pos + 5] = static_cast((value >> 16u) & 0xffu); target[pos + 6] = static_cast((value >> 8u) & 0xffu); target[pos + 7] = static_cast((value >> 0u) & 0xffu); } return pos + 8; } inline std::size_t writeBuffer(std::span& target, std::size_t pos, std::span value) { if ((pos + value.size()) > target.size()) { if (pos < target.size()) { std::size_t const n = target.size() - pos; std::copy(value.begin(), value.begin() + n, target.begin() + pos); } } else { std::copy(value.begin(), value.end(), target.begin() + pos); } return pos + value.size(); } inline std::size_t alignNextWrite(std::span& target, std::size_t pos, std::size_t alignment) { std::ignore = target; if (alignment <= 1) { return pos; } if (pos % alignment == 0) { return pos; } return ((pos + alignment - 1) / alignment) * alignment; } } // namespace monoformat #endif // MONOFORMAT_PARSEHELPERS_HPP