From b2f126cebedca300f7021b8370e558b2b0862ba2 Mon Sep 17 00:00:00 2001 From: John Chadwick Date: Sat, 7 Sep 2019 13:20:16 -0700 Subject: [PATCH] Implement write support for some primitives. This should be enough to enable serialization of very basic seqs for the C++ code generator in the future. --- CMakeLists.txt | 2 + kaitai/kostream.cpp | 178 ++++++++++++++++++++++++++++++++++++++++++++ kaitai/kostream.h | 119 +++++++++++++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 kaitai/kostream.cpp create mode 100644 kaitai/kostream.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c747e9..9a40d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,11 +20,13 @@ set (HEADERS kaitai/kaitaistruct.h kaitai/kio.h kaitai/kistream.h + kaitai/kostream.h ) set (SOURCES kaitai/kio.cpp kaitai/kistream.cpp + kaitai/kostream.cpp ) set(STRING_ENCODING_TYPE "ICONV" CACHE STRING "Set the way strings have to be encoded (ICONV|NONE|...)") diff --git a/kaitai/kostream.cpp b/kaitai/kostream.cpp new file mode 100644 index 0000000..6dcd2df --- /dev/null +++ b/kaitai/kostream.cpp @@ -0,0 +1,178 @@ +#include +#include + +#include +#include +#include + +kaitai::kostream::kostream(std::ostream* io): kio(io) { + m_io = io; +} + +// ======================================================================== +// Integer numbers +// ======================================================================== + +// ------------------------------------------------------------------------ +// Signed +// ------------------------------------------------------------------------ + +void kaitai::kostream::write_s1(int8_t t) { + m_io->put(t); +} + +// ........................................................................ +// Big-endian +// ........................................................................ + +void kaitai::kostream::write_s2be(int16_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_16(t); +#endif + m_io->write(reinterpret_cast(&t), 2); +} + +void kaitai::kostream::write_s4be(int32_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 4); +} + +void kaitai::kostream::write_s8be(int64_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +void kaitai::kostream::write_s2le(int16_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_16(t); +#endif + m_io->write(reinterpret_cast(&t), 2); +} + +void kaitai::kostream::write_s4le(int32_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 4); +} + +void kaitai::kostream::write_s8le(int64_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ------------------------------------------------------------------------ +// Unsigned +// ------------------------------------------------------------------------ + +void kaitai::kostream::write_u1(uint8_t t) { + m_io->put(t); +} + +// ........................................................................ +// Big-endian +// ........................................................................ + +void kaitai::kostream::write_u2be(uint16_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_16(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +void kaitai::kostream::write_u4be(uint32_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +void kaitai::kostream::write_u8be(uint64_t t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +void kaitai::kostream::write_u2le(uint16_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_16(t); +#endif + m_io->write(reinterpret_cast(&t), 2); +} + +void kaitai::kostream::write_u4le(uint32_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 4); +} + +void kaitai::kostream::write_u8le(uint64_t t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ======================================================================== +// Floating point numbers +// ======================================================================== + +// ........................................................................ +// Big-endian +// ........................................................................ + +void kaitai::kostream::write_f4be(float t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 4); +} + +void kaitai::kostream::write_f8be(double t) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +void kaitai::kostream::write_f4le(float t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + m_io->write(reinterpret_cast(&t), 4); +} + +void kaitai::kostream::write_f8le(double t) { +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + m_io->write(reinterpret_cast(&t), 8); +} + +// ======================================================================== +// Byte arrays +// ======================================================================== + +void kaitai::kostream::write_bytes(std::string bytes) { + m_io->write(bytes.data(), bytes.length()); +} diff --git a/kaitai/kostream.h b/kaitai/kostream.h new file mode 100644 index 0000000..a638be1 --- /dev/null +++ b/kaitai/kostream.h @@ -0,0 +1,119 @@ +#ifndef KAITAI_KOSTREAM_H +#define KAITAI_KOSTREAM_H + +#include + +#include +#include +#include +#include + +namespace kaitai { + +/** + * Kaitai Output Stream class (kaitai::kostream) is an implementation of + * Kaitai Struct stream API + * for C++/STL, for serialization. It's implemented as a wrapper over generic + * STL std::ostream. + * + * It provides a wide variety of simple methods to write (serialize) binary + * representations of primitive types, such as integer and floating + * point numbers, byte arrays and strings, with unified cross-language and + * cross-toolkit semantics. + * + * Typically, end users won't access Kaitai Stream classes manually, but would + * describe a binary structure format using .ksy language and then would use + * Kaitai Struct compiler to generate source code in desired target language. + * That code, in turn, would use this class and API to do the actual parsing + * job. + */ +class kostream : public virtual kio { +public: + /** + * Constructs new Kaitai Stream object, wrapping a given std::istream. + * \param io istream object to use for this Kaitai Stream + */ + kostream(std::ostream* io); + + /** @name Integer numbers */ + //@{ + + // ------------------------------------------------------------------------ + // Signed + // ------------------------------------------------------------------------ + + void write_s1(int8_t t); + + // ........................................................................ + // Big-endian + // ........................................................................ + + void write_s2be(int16_t t); + void write_s4be(int32_t t); + void write_s8be(int64_t t); + + // ........................................................................ + // Little-endian + // ........................................................................ + + void write_s2le(int16_t t); + void write_s4le(int32_t t); + void write_s8le(int64_t t); + + // ------------------------------------------------------------------------ + // Unsigned + // ------------------------------------------------------------------------ + + void write_u1(uint8_t t); + + // ........................................................................ + // Big-endian + // ........................................................................ + + void write_u2be(uint16_t t); + void write_u4be(uint32_t t); + void write_u8be(uint64_t t); + + // ........................................................................ + // Little-endian + // ........................................................................ + + void write_u2le(uint16_t t); + void write_u4le(uint32_t t); + void write_u8le(uint64_t t); + + //@} + + /** @name Floating point numbers */ + //@{ + + // ........................................................................ + // Big-endian + // ........................................................................ + + void write_f4be(float t); + void write_f8be(double t); + + // ........................................................................ + // Little-endian + // ........................................................................ + + void write_f4le(float t); + void write_f8le(double t); + + //@} + + /** @name Byte arrays */ + //@{ + + void write_bytes(std::string bytes); + + //@} + +private: + std::ostream* m_io; +}; + +} + +#endif