From 13e18cf59686319efee0080d523c4bc2d948b591 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Wed, 12 May 2021 15:00:44 +0200 Subject: add xdr --- include/lib/xdr.h | 66 ++++++++++++++++ include/lib/xdr16.h | 68 +++++++++++++++++ src/lib/xdr.cc | 188 +++++++++++++++++++++++++++++++++++++++++++++ src/lib/xdr16.cc | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 538 insertions(+) create mode 100644 include/lib/xdr.h create mode 100644 include/lib/xdr16.h create mode 100644 src/lib/xdr.cc create mode 100644 src/lib/xdr16.cc diff --git a/include/lib/xdr.h b/include/lib/xdr.h new file mode 100644 index 0000000..c451a2f --- /dev/null +++ b/include/lib/xdr.h @@ -0,0 +1,66 @@ +#ifndef XDR_H +#define XDR_H + +#include + +class XDRWriter +{ +private: + XDRWriter(const XDRWriter ©); + char *buffer; + uint32_t next_array_len; + uint32_t pos; + bool is_fixed_length; + +public: + XDRWriter(char *output_buf) : buffer(output_buf), next_array_len(0), pos(0) {} + + inline void setNextArrayLen(uint32_t len) { next_array_len = len; } + inline void setFixedLength() { is_fixed_length = true; } + inline void setVariableLength() { is_fixed_length = false; } + inline void startList() + { + if (!is_fixed_length) + { + put(next_array_len); + } + } + + inline void put(char c) { put((int32_t)c); } + inline void put(unsigned char c) { put((uint32_t)c); } + inline void put(uint16_t number) { put((int32_t)number); } + inline void put(int16_t number) { put((uint32_t)number); } + void put(uint32_t number); + void put(int32_t number); + void put(uint64_t number); + void put(int64_t number); + void put(float number); + void put(double number); + void put(char const *text); + template + void put(char const (&text)[TSize]); + + inline uint32_t size() { return pos; } +}; + +class XDRReader +{ +private: + XDRReader(const XDRReader ©); + char *data; + uint32_t pos; + +public: + XDRReader(char *d) : pos(0) { data = d; } + uint32_t get_uint32(); + int32_t get_int32(); + uint64_t get_uint64(); + int64_t get_int64(); + float get_float(); + double get_double(); + uint32_t get_opaque_length(); + char *get_opaque(uint32_t length); + void get_string(char *target); +}; + +#endif diff --git a/include/lib/xdr16.h b/include/lib/xdr16.h new file mode 100644 index 0000000..483efe4 --- /dev/null +++ b/include/lib/xdr16.h @@ -0,0 +1,68 @@ +#ifndef XDR16_H +#define XDR16_H + +#include + +class XDRWriter +{ +private: + XDRWriter(const XDRWriter ©); + char *buffer; + uint16_t next_array_len; + uint16_t pos; + bool is_fixed_length; + +public: + XDRWriter(char *output_buf) : buffer(output_buf), next_array_len(0), pos(0) {} + + inline void setNextArrayLen(uint16_t len) { next_array_len = len; } + inline void setFixedLength() { is_fixed_length = true; } + inline void setVariableLength() { is_fixed_length = false; } + inline void startList() + { + if (!is_fixed_length) + { + put(next_array_len); + } + } + + inline void put(char c) { put((int16_t)c); } + inline void put(unsigned char c) { put((uint16_t)c); } + void put(uint16_t number); + void put(int16_t number); + void put(uint32_t number); + void put(int32_t number); + void put(uint64_t number); + void put(int64_t number); + void put(float number); + void put(double number); + void put(char const *text); + template + void put(char const (&text)[TSize]); + + inline uint16_t size() { return pos; } +}; + +class XDRReader +{ +private: + XDRReader(const XDRReader ©); + char *data; + uint32_t pos; + +public: + XDRReader(char *d) : pos(0) { data = d; } + int16_t get_int16(); + uint16_t get_uint16(); + uint32_t get_uint32(); + int32_t get_int32(); + uint64_t get_uint64(); + int64_t get_int64(); + float get_float(); + double get_double(); + uint32_t get_opaque_length(); + char *get_opaque(uint32_t length); + void get_string(char *target); +}; + +#endif diff --git a/src/lib/xdr.cc b/src/lib/xdr.cc new file mode 100644 index 0000000..b44471f --- /dev/null +++ b/src/lib/xdr.cc @@ -0,0 +1,188 @@ +#include "lib/xdr.h" + +void XDRWriter::put(uint32_t number) +{ + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 4; +} + +void XDRWriter::put(int32_t number) +{ + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 4; +} + +void XDRWriter::put(uint64_t number) +{ + *buffer++ = ((number >> 56) & 0xffU); + *buffer++ = ((number >> 48) & 0xffU); + *buffer++ = ((number >> 40) & 0xffU); + *buffer++ = ((number >> 32) & 0xffU); + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 8; +} + +void XDRWriter::put(int64_t number) +{ + *buffer++ = ((number >> 56) & 0xffU); + *buffer++ = ((number >> 48) & 0xffU); + *buffer++ = ((number >> 40) & 0xffU); + *buffer++ = ((number >> 32) & 0xffU); + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 8; +} + +void XDRWriter::put(float number) +{ + union { + uint32_t i; + float f; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.f = number; + put(v.i); +} + +void XDRWriter::put(double number) +{ + union { + uint64_t i; + double d; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.d = number; + put(v.i); +} + +void XDRWriter::put(char const *data) +{ + if (!is_fixed_length) + { + put(next_array_len); + } + uint32_t i; + for (i = 0; i < next_array_len; i++) + { + *buffer++ = data[i]; + } + while ((i++) % 4 != 0) + { + *buffer++ = 0; + } + pos += i - 1; +} + +template +void XDRWriter::put(char const (&data)[TSize]) +{ + if (!is_fixed_length) + { + put(TSize); + } + uint32_t i; + for (i = 0; i < TSize; i++) + { + *buffer++ = data[i]; + } + while ((i++) % 4 != 0) + { + *buffer++ = 0; + } + pos += i - 1; +} + +uint32_t XDRReader::get_uint32() +{ + uint32_t ret = (((uint32_t)data[pos] & 0xffU) << 24) | (((uint32_t)data[pos + 1] & 0xffU) << 16) | (((uint32_t)data[pos + 2] & 0xffU) << 8) | ((uint32_t)data[pos + 3] & 0xffU); + pos += 4; + return ret; +} + +int32_t XDRReader::get_int32() +{ + int32_t ret = (((int32_t)data[pos] & 0xff) << 24) | (((int32_t)data[pos + 1] & 0xff) << 16) | (((int32_t)data[pos + 2] & 0xff) << 8) | ((int32_t)data[pos + 3] & 0xff); + pos += 4; + return ret; +} + +uint64_t XDRReader::get_uint64() +{ + uint64_t ret = (((uint64_t)data[pos] & 0xffU) << 56) | (((uint64_t)data[pos + 1] & 0xffU) << 48) | (((uint64_t)data[pos + 2] & 0xffU) << 40) | (((uint64_t)data[pos + 3] & 0xffU) << 32) | (((uint64_t)data[pos + 4] & 0xffU) << 24) | (((uint64_t)data[pos + 5] & 0xffU) << 16) | (((uint64_t)data[pos + 6] & 0xffU) << 8) | ((uint64_t)data[pos + 7] & 0xffU); + return ret; +} + +int64_t XDRReader::get_int64() +{ + int64_t ret = (((int64_t)data[pos] & 0xff) << 56) | (((int64_t)data[pos + 1] & 0xff) << 48) | (((int64_t)data[pos + 2] & 0xff) << 40) | (((int64_t)data[pos + 3] & 0xff) << 32) | (((int64_t)data[pos + 4] & 0xff) << 24) | (((int64_t)data[pos + 5] & 0xff) << 16) | (((int64_t)data[pos + 6] & 0xff) << 8) | ((int64_t)data[pos + 7] & 0xff); + return ret; +} + +float XDRReader::get_float() +{ + union { + uint32_t i; + float f; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.i = get_uint32(); + return v.f; +} + +double XDRReader::get_double() +{ + union { + uint64_t i; + double d; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.i = get_uint64(); + return v.d; +} + +uint32_t XDRReader::get_opaque_length() +{ + return get_uint32(); +} + +char *XDRReader::get_opaque(uint32_t length) +{ + char *ret = data + pos; + pos += length; + if (length % 4) + { + pos += 4 - (length % 4); + } + return ret; +} + +void XDRReader::get_string(char *target) +{ + uint16_t length = get_opaque_length(); + uint16_t i; + for (i = 0; i < length; i++) + { + target[i] = data[pos + i]; + } + target[i] = 0; + pos += length; + if (length % 4) + { + pos += 4 - (length % 4); + } +} diff --git a/src/lib/xdr16.cc b/src/lib/xdr16.cc new file mode 100644 index 0000000..b1fb7ca --- /dev/null +++ b/src/lib/xdr16.cc @@ -0,0 +1,216 @@ +#include "lib/xdr16.h" + +void XDRWriter::put(uint16_t number) +{ + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 2; +} + +void XDRWriter::put(int16_t number) +{ + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 2; +} + +void XDRWriter::put(uint32_t number) +{ + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 4; +} + +void XDRWriter::put(int32_t number) +{ + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 4; +} + +void XDRWriter::put(uint64_t number) +{ + *buffer++ = ((number >> 56) & 0xffU); + *buffer++ = ((number >> 48) & 0xffU); + *buffer++ = ((number >> 40) & 0xffU); + *buffer++ = ((number >> 32) & 0xffU); + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 8; +} + +void XDRWriter::put(int64_t number) +{ + *buffer++ = ((number >> 56) & 0xffU); + *buffer++ = ((number >> 48) & 0xffU); + *buffer++ = ((number >> 40) & 0xffU); + *buffer++ = ((number >> 32) & 0xffU); + *buffer++ = ((number >> 24) & 0xffU); + *buffer++ = ((number >> 16) & 0xffU); + *buffer++ = ((number >> 8) & 0xffU); + *buffer++ = (number & 0xffU); + pos += 8; +} + +void XDRWriter::put(float number) +{ + union { + uint32_t i; + float f; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.f = number; + put(v.i); +} + +void XDRWriter::put(double number) +{ + union { + uint64_t i; + double d; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.d = number; + put(v.i); +} + +void XDRWriter::put(char const *data) +{ + if (!is_fixed_length) + { + put(next_array_len); + } + uint16_t i; + for (i = 0; i < next_array_len; i++) + { + *buffer++ = data[i]; + } + while ((i++) % 2 != 0) + { + *buffer++ = 0; + } + pos += i - 1; +} + +template +void XDRWriter::put(char const (&data)[TSize]) +{ + if (!is_fixed_length) + { + put(TSize); + } + uint16_t i; + for (i = 0; i < TSize; i++) + { + *buffer++ = data[i]; + } + while ((i++) % 2 != 0) + { + *buffer++ = 0; + } + pos += i - 1; +} + +uint16_t XDRReader::get_uint16() +{ + uint16_t ret = (((uint16_t)data[pos] & 0xffU) << 8) | ((uint16_t)data[pos + 1] & 0xffU); + pos += 2; + return ret; +} + +int16_t XDRReader::get_int16() +{ + int16_t ret = (((int16_t)data[pos] & 0xff) << 8) | ((int16_t)data[pos + 1] & 0xff); + pos += 2; + return ret; +} + +uint32_t XDRReader::get_uint32() +{ + uint32_t ret = (((uint32_t)data[pos] & 0xffU) << 24) | (((uint32_t)data[pos + 1] & 0xffU) << 16) | (((uint32_t)data[pos + 2] & 0xffU) << 8) | ((uint32_t)data[pos + 3] & 0xffU); + pos += 4; + return ret; +} + +int32_t XDRReader::get_int32() +{ + int32_t ret = (((int32_t)data[pos] & 0xff) << 24) | (((int32_t)data[pos + 1] & 0xff) << 16) | (((int32_t)data[pos + 2] & 0xff) << 8) | ((int32_t)data[pos + 3] & 0xff); + pos += 4; + return ret; +} + +uint64_t XDRReader::get_uint64() +{ + uint64_t ret = (((uint64_t)data[pos] & 0xffU) << 56) | (((uint64_t)data[pos + 1] & 0xffU) << 48) | (((uint64_t)data[pos + 2] & 0xffU) << 40) | (((uint64_t)data[pos + 3] & 0xffU) << 32) | (((uint64_t)data[pos + 4] & 0xffU) << 24) | (((uint64_t)data[pos + 5] & 0xffU) << 16) | (((uint64_t)data[pos + 6] & 0xffU) << 8) | ((uint64_t)data[pos + 7] & 0xffU); + return ret; +} + +int64_t XDRReader::get_int64() +{ + int64_t ret = (((int64_t)data[pos] & 0xff) << 56) | (((int64_t)data[pos + 1] & 0xff) << 48) | (((int64_t)data[pos + 2] & 0xff) << 40) | (((int64_t)data[pos + 3] & 0xff) << 32) | (((int64_t)data[pos + 4] & 0xff) << 24) | (((int64_t)data[pos + 5] & 0xff) << 16) | (((int64_t)data[pos + 6] & 0xff) << 8) | ((int64_t)data[pos + 7] & 0xff); + return ret; +} + +float XDRReader::get_float() +{ + union { + uint32_t i; + float f; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.i = get_uint32(); + return v.f; +} + +double XDRReader::get_double() +{ + union { + uint64_t i; + double d; + } v; + // Setting one member of a struct and then reading another is undefined + // behaviour, but works as intended in nearly any (embedded) compiler + v.i = get_uint64(); + return v.d; +} + +uint32_t XDRReader::get_opaque_length() +{ + return get_uint16(); +} + +char *XDRReader::get_opaque(uint32_t length) +{ + char *ret = data + pos; + pos += length; + if (length % 2) + { + pos += 2 - (length % 2); + } + return ret; +} + +void XDRReader::get_string(char *target) +{ + uint16_t length = get_opaque_length(); + uint16_t i; + for (i = 0; i < length; i++) + { + target[i] = data[pos + i]; + } + target[i] = 0; + pos += length; + if (length % 2) + { + pos += 2 - (length % 2); + } +} -- cgit v1.2.3