From 4853a5593cc6147e1851e537b46a5128792939a5 Mon Sep 17 00:00:00 2001
From: Daniel Friesel <derf@finalrewind.org>
Date: Tue, 25 Sep 2018 08:32:16 +0200
Subject: [PATCH] Your Templates are Bad and You Should Feel Bad

---
 include/object/xdrstream.h | 10 +++++++++-
 src/app/prototest/main.cc  | 10 ++++++++--
 src/os/object/xdrstream.cc | 33 ++++++++++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/include/object/xdrstream.h b/include/object/xdrstream.h
index 717822e..432f952 100644
--- a/include/object/xdrstream.h
+++ b/include/object/xdrstream.h
@@ -7,10 +7,13 @@ class XDRStream {
  private:
 	XDRStream(const XDRStream& copy);
 	uint32_t next_array_len;
+	bool is_fixed_length;
 
  public:
 	XDRStream() : next_array_len(0) {}
 	void setNextArrayLen(uint32_t len) {next_array_len = len;}
+	void setFixedLength() { is_fixed_length = true; }
+	void setVariableLength() { is_fixed_length = false; }
 
 	virtual void put(char c) = 0;
 
@@ -26,7 +29,8 @@ class XDRStream {
 	XDRStream & operator<<(long number);
 	XDRStream & operator<<(unsigned long long number);
 	XDRStream & operator<<(long long number);
-	XDRStream & operator<<(const char *text);
+	XDRStream & operator<<(char const *text);
+	template<int N> XDRStream & operator<<(char const (&text)[N]);
 	XDRStream & operator<<(XDRStream & (*fun) (XDRStream &));
 };
 
@@ -37,6 +41,10 @@ XDRStream & flush(XDRStream & os);
 // TERM: zero-termination
 XDRStream & term(XDRStream & os);
 
+template<int N>
 XDRStream & opaque(XDRStream & os);
 
+XDRStream & fixed(XDRStream & os);
+XDRStream & variable(XDRStream & os);
+
 #endif //OUTPUTSTREAM_H
diff --git a/src/app/prototest/main.cc b/src/app/prototest/main.cc
index 8613bea..c17b69d 100644
--- a/src/app/prototest/main.cc
+++ b/src/app/prototest/main.cc
@@ -6,7 +6,7 @@
 #include "object/stdbuf.h"
 #include "object/xdrstream.h"
 
-char buf[128];
+char buf[256];
 
 void loop(void)
 {
@@ -30,10 +30,16 @@ void loop(void)
 
 	BufferOutput<XDRStream> foostream(buf);
 
+	char test[] = "Obai World!";
+
 	foostream << 123 << 0 << 12345678;
+	foostream.setNextArrayLen(3);
+	foostream << fixed << "Hai";
+	foostream.setNextArrayLen(sizeof(test));
+	foostream << variable << (char const *)test;
 
 	kout << "foostream is " << hex;
-	for (unsigned int i = 0; i < 32; i += 4) {
+	for (unsigned int i = 0; i < 64; i += 4) {
 		kout << (unsigned char)buf[i] << (unsigned char)buf[i+1];
 		kout << (unsigned char)buf[i+2] << (unsigned char)buf[i+3] << " ";
 	}
diff --git a/src/os/object/xdrstream.cc b/src/os/object/xdrstream.cc
index eb5ca87..d7a5ace 100644
--- a/src/os/object/xdrstream.cc
+++ b/src/os/object/xdrstream.cc
@@ -69,6 +69,9 @@ XDRStream & XDRStream::operator<<(int64_t number)
 }
 
 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]);
@@ -79,6 +82,21 @@ XDRStream & XDRStream::operator<<(char const *data){
 	return *this;
 }
 
+template<int N>
+XDRStream & XDRStream::operator<<(char const (&data)[N]){
+	if (!is_fixed_length) {
+		*this << N;
+	}
+	uint32_t i;
+	for (i = 0; i < N; i++) {
+		put(data[i]);
+	}
+	while ((i++) % 4 != 0){
+		put('\0');
+	}
+	return *this;
+}
+
 XDRStream & XDRStream::operator<<(XDRStream & (*fkt) (XDRStream &))
 {
 	return fkt(*this);
@@ -99,8 +117,21 @@ XDRStream & term(XDRStream & os)
 	return os;
 }
 
+template<int N>
 XDRStream & opaque(XDRStream & os)
 {
-	os.setNextArrayLen(3);
+	os.setNextArrayLen(N);
+	return os;
+}
+
+XDRStream & fixed(XDRStream & os)
+{
+	os.setFixedLength();
+	return os;
+}
+
+XDRStream & variable(XDRStream & os)
+{
+	os.setVariableLength();
 	return os;
 }
-- 
GitLab