From 2c001e655002ee713457342197a7005217cd16b4 Mon Sep 17 00:00:00 2001
From: Daniel Friesel <daniel.friesel@uos.de>
Date: Wed, 26 Jun 2019 14:40:30 +0200
Subject: [PATCH] Add a 16-bit XDR variant

---
 include/object/xdr16input.h    |  27 ++++++
 include/object/xdr16stream.h   |  50 ++++++++++
 src/app/prototest/Makefile.inc |   5 +
 src/app/prototest/main.cc      |   5 +
 src/os/object/xdr16input.cc    |  99 ++++++++++++++++++++
 src/os/object/xdr16stream.cc   | 161 +++++++++++++++++++++++++++++++++
 6 files changed, 347 insertions(+)
 create mode 100644 include/object/xdr16input.h
 create mode 100644 include/object/xdr16stream.h
 create mode 100644 src/os/object/xdr16input.cc
 create mode 100644 src/os/object/xdr16stream.cc

diff --git a/include/object/xdr16input.h b/include/object/xdr16input.h
new file mode 100644
index 0000000..66b2c56
--- /dev/null
+++ b/include/object/xdr16input.h
@@ -0,0 +1,27 @@
+#ifndef XDRINPUT_H
+#define XDRINPUT_H
+
+#include <stdint.h>
+
+class XDRInput {
+	private:
+		XDRInput(const XDRInput& copy);
+		char *data;
+		uint32_t pos;
+
+	public:
+		XDRInput(char *d) : pos(0) { data = d; }
+		uint16_t get_uint16();
+		int16_t get_int16();
+		uint32_t get_uint32();
+		int32_t get_int32();
+		uint64_t get_uint64();
+		int64_t get_int64();
+		float get_float();
+		double get_double();
+		uint16_t get_opaque_length();
+		char* get_opaque(uint16_t length);
+		void get_string(char *target);
+};
+
+#endif
diff --git a/include/object/xdr16stream.h b/include/object/xdr16stream.h
new file mode 100644
index 0000000..7cec1b1
--- /dev/null
+++ b/include/object/xdr16stream.h
@@ -0,0 +1,50 @@
+#ifndef XDRSTREAM_H
+#define XDRSTREAM_H
+
+#include <stdint.h>
+
+class XDRStream {
+ private:
+	XDRStream(const XDRStream& copy);
+	uint16_t next_array_len;
+	bool is_fixed_length;
+
+ public:
+	XDRStream() : next_array_len(0) {}
+	void setNextArrayLen(uint16_t len) {next_array_len = len;}
+	void setFixedLength() { is_fixed_length = true; }
+	void setVariableLength() { is_fixed_length = false; }
+
+	virtual void put(char c) = 0;
+
+	virtual void flush() {}
+
+	XDRStream & operator<<(char c);
+	XDRStream & operator<<(unsigned char c);
+	XDRStream & operator<<(uint16_t number);
+	XDRStream & operator<<(int16_t number);
+	XDRStream & operator<<(uint32_t number);
+	XDRStream & operator<<(int32_t number);
+	XDRStream & operator<<(uint64_t number);
+	XDRStream & operator<<(int64_t number);
+	XDRStream & operator<<(float number);
+	XDRStream & operator<<(double number);
+	XDRStream & operator<<(char const *text);
+	template<uint16_t TSize> XDRStream & operator<<(char const (&text)[TSize]);
+	XDRStream & operator<<(XDRStream & (*fun) (XDRStream &));
+};
+
+
+// FLUSH: flush XDRStream buffer
+XDRStream & flush(XDRStream & os);
+
+// TERM: zero-termination
+XDRStream & term(XDRStream & os);
+
+template<int TSize>
+XDRStream & opaque(XDRStream & os);
+
+XDRStream & fixed(XDRStream & os);
+XDRStream & variable(XDRStream & os);
+
+#endif //OUTPUTSTREAM_H
diff --git a/src/app/prototest/Makefile.inc b/src/app/prototest/Makefile.inc
index a33fd48..ee509a7 100644
--- a/src/app/prototest/Makefile.inc
+++ b/src/app/prototest/Makefile.inc
@@ -72,6 +72,11 @@ ifeq (${prototest_xdr}, 1)
 	CXX_TARGETS += src/os/object/xdrstream.cc src/os/object/xdrinput.cc
 endif
 
+ifeq (${prototest_xdr16}, 1)
+	COMMON_FLAGS += -DPROTOTEST_XDR16
+	CXX_TARGETS += src/os/object/xdr16stream.cc src/os/object/xdr16input.cc
+endif
+
 # Don't try to make .capnp from .capnp.c
 %.capnp: ;
 
diff --git a/src/app/prototest/main.cc b/src/app/prototest/main.cc
index d470d59..ee5c958 100644
--- a/src/app/prototest/main.cc
+++ b/src/app/prototest/main.cc
@@ -39,6 +39,11 @@
 #include "object/xdrstream.h"
 #include "object/xdrinput.h"
 #endif
+#ifdef PROTOTEST_XDR16
+#include "object/stdbuf.h"
+#include "object/xdr16stream.h"
+#include "object/xdr16input.h"
+#endif
 
 #include <stdint.h>
 
diff --git a/src/os/object/xdr16input.cc b/src/os/object/xdr16input.cc
new file mode 100644
index 0000000..407f6ea
--- /dev/null
+++ b/src/os/object/xdr16input.cc
@@ -0,0 +1,99 @@
+#include "object/xdr16input.h"
+
+uint16_t XDRInput::get_uint16()
+{
+	uint32_t ret = ((uint8_t)data[pos]<<8) | (uint8_t)data[pos+1];
+	pos += 2;
+	return ret;
+}
+
+int16_t XDRInput::get_int16()
+{
+	int32_t ret = (data[pos]<<8) | data[pos+1];
+	pos += 2;
+	return ret;
+}
+
+uint32_t XDRInput::get_uint32()
+{
+	uint32_t ret = ((uint8_t)data[pos]<<24) | ((uint8_t)data[pos+1]<<16)
+		| ((uint8_t)data[pos+2]<<8) | (uint8_t)data[pos+3];
+	pos += 4;
+	return ret;
+}
+
+int32_t XDRInput::get_int32()
+{
+	int32_t ret = (data[pos]<<24) | (data[pos+1]<<16) | (data[pos+2]<<8) | data[pos+3];
+	pos += 4;
+	return ret;
+}
+
+uint64_t XDRInput::get_uint64()
+{
+	uint64_t ret0 = ((uint8_t)data[pos]<<24) | ((uint8_t)data[pos+1]<<16)
+		| ((uint8_t)data[pos+2]<<8) | (uint8_t)data[pos+3];
+	pos += 4;
+	uint64_t ret1 = ((uint8_t)data[pos]<<24) | ((uint8_t)data[pos+1]<<16)
+		| ((uint8_t)data[pos+2]<<8) | (uint8_t)data[pos+3];
+	pos += 4;
+	return (ret0 << 32) | ret1;
+}
+
+int64_t XDRInput::get_int64()
+{
+	int64_t ret0 = (data[pos]<<24) | (data[pos+1]<<16) | (data[pos+2]<<8) | data[pos+3];
+	pos += 4;
+	int64_t ret1 = (data[pos]<<24) | (data[pos+1]<<16) | (data[pos+2]<<8) | data[pos+3];
+	pos += 4;
+	return (ret0 << 32) | ret1;
+}
+
+float XDRInput::get_float()
+{
+	union {
+		uint32_t i;
+		float f;
+	} v;
+	v.i = get_uint32();
+	return v.f;
+}
+
+double XDRInput::get_double()
+{
+	union {
+		uint64_t i;
+		double d;
+	} v;
+	v.i = get_uint64();
+	return v.d;
+}
+
+uint16_t XDRInput::get_opaque_length()
+{
+	return get_uint16();
+}
+
+char *XDRInput::get_opaque(uint16_t length)
+{
+	char *ret = data + pos;
+	pos += length;
+	if (length % 2) {
+		pos += 2 - (length % 2);
+	}
+	return ret;
+}
+
+void XDRInput::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);
+	}
+}
diff --git a/src/os/object/xdr16stream.cc b/src/os/object/xdr16stream.cc
new file mode 100644
index 0000000..082b2a3
--- /dev/null
+++ b/src/os/object/xdr16stream.cc
@@ -0,0 +1,161 @@
+#include "object/xdr16stream.h"
+
+XDRStream & XDRStream::operator<<(unsigned char c)
+{
+	*this << (uint16_t)c;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(char c)
+{
+	*this << (int16_t)c;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint16_t number)
+{
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int16_t number)
+{
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint32_t number)
+{
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int32_t number)
+{
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint64_t number)
+{
+	put((number >> 56) & 0xffU);
+	put((number >> 48) & 0xffU);
+	put((number >> 40) & 0xffU);
+	put((number >> 32) & 0xffU);
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int64_t number)
+{
+	put((number >> 56) & 0xffU);
+	put((number >> 48) & 0xffU);
+	put((number >> 40) & 0xffU);
+	put((number >> 32) & 0xffU);
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(float number)
+{
+	union {
+		uint32_t i;
+		float f;
+	} v;
+	v.f = number;
+	*this << v.i;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(double number)
+{
+	union {
+		uint64_t i;
+		double d;
+	} v;
+	v.d = number;
+	*this << v.i;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(char const *data){
+	if (!is_fixed_length) {
+		*this << next_array_len;
+	}
+	uint32_t i;
+	for (i = 0; i < next_array_len; i++) {
+		put(data[i]);
+	}
+	while ((i++) % 2 != 0){
+		put('\0');
+	}
+	return *this;
+}
+
+template<uint16_t TSize>
+XDRStream & XDRStream::operator<<(char const (&data)[TSize]){
+	if (!is_fixed_length) {
+		*this << TSize;
+	}
+	uint32_t i;
+	for (i = 0; i < TSize; i++) {
+		put(data[i]);
+	}
+	while ((i++) % 2 != 0){
+		put('\0');
+	}
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(XDRStream & (*fkt) (XDRStream &))
+{
+	return fkt(*this);
+}
+
+// FLUSH
+XDRStream & flush(XDRStream & os)
+{
+	os.flush();
+	return os;
+}
+
+// TERM: null-termination
+XDRStream & term(XDRStream & os)
+{
+	os.put('\0');
+	os.flush();
+	return os;
+}
+
+template<int N>
+XDRStream & opaque(XDRStream & os)
+{
+	os.setNextArrayLen(N);
+	return os;
+}
+
+XDRStream & fixed(XDRStream & os)
+{
+	os.setFixedLength();
+	return os;
+}
+
+XDRStream & variable(XDRStream & os)
+{
+	os.setVariableLength();
+	return os;
+}
-- 
GitLab