From d5b0bb69df182651f0247c853adf8b997f2cbcc8 Mon Sep 17 00:00:00 2001
From: Gary Talent <gtalent2@gmail.com>
Date: Tue, 13 Feb 2018 19:13:31 -0600
Subject: [PATCH] Start fleshing out tracing library

---
 deps/ox/src/ox/std/CMakeLists.txt |  1 +
 deps/ox/src/ox/std/math.hpp       | 11 ++++++
 deps/ox/src/ox/std/std.hpp        |  1 +
 deps/ox/src/ox/std/string.hpp     | 31 +++++++++++++++
 deps/ox/src/ox/std/strops.cpp     | 29 ++++++++++++++
 deps/ox/src/ox/std/strops.hpp     |  3 ++
 deps/ox/src/ox/std/typetraits.hpp | 63 +++++++++++++++++++++++++++++++
 deps/ox/src/ox/trace/trace.cpp    | 17 +++------
 deps/ox/src/ox/trace/trace.hpp    | 31 ++++++++++++++-
 9 files changed, 173 insertions(+), 14 deletions(-)
 create mode 100644 deps/ox/src/ox/std/typetraits.hpp

diff --git a/deps/ox/src/ox/std/CMakeLists.txt b/deps/ox/src/ox/std/CMakeLists.txt
index 5bd0ac2b..f30a3481 100644
--- a/deps/ox/src/ox/std/CMakeLists.txt
+++ b/deps/ox/src/ox/std/CMakeLists.txt
@@ -24,6 +24,7 @@ install(
 		strops.hpp
 		std.hpp
 		types.hpp
+		typetraits.hpp
 	DESTINATION
 		include/ox/std
 )
diff --git a/deps/ox/src/ox/std/math.hpp b/deps/ox/src/ox/std/math.hpp
index 6cb6c7f6..71fa2f65 100644
--- a/deps/ox/src/ox/std/math.hpp
+++ b/deps/ox/src/ox/std/math.hpp
@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include "typetraits.hpp"
+
 namespace ox {
 
 template<typename T>
@@ -20,4 +22,13 @@ inline const T &max(const T &a, const T &b) {
 	return a > b ? a : b;
 }
 
+template<typename I>
+inline I pow(I v, int e) {
+	I out = 1;
+	for (I i = 0; i < e; i++) {
+		out *= v;
+	}
+	return out;
+}
+
 }
diff --git a/deps/ox/src/ox/std/std.hpp b/deps/ox/src/ox/std/std.hpp
index 9613abab..32164470 100644
--- a/deps/ox/src/ox/std/std.hpp
+++ b/deps/ox/src/ox/std/std.hpp
@@ -16,4 +16,5 @@
 #include "strops.hpp"
 #include "string.hpp"
 #include "types.hpp"
+#include "typetraits.hpp"
 #include "vector.hpp"
diff --git a/deps/ox/src/ox/std/string.hpp b/deps/ox/src/ox/std/string.hpp
index 2677d46c..a7e7d289 100644
--- a/deps/ox/src/ox/std/string.hpp
+++ b/deps/ox/src/ox/std/string.hpp
@@ -29,6 +29,12 @@ class BString {
 
 		const BString &operator=(char *str);
 
+		const BString &operator=(int64_t i);
+
+		const BString &operator+=(const char *str);
+
+		const BString &operator+=(char *str);
+
 		bool operator==(const BString &other);
 
 		char *data();
@@ -59,6 +65,13 @@ BString<size>::BString(const char *str) {
 	*this = str;
 }
 
+template<size_t size>
+const BString<size> &BString<size>::operator=(int64_t i) {
+	char str[65];
+	ox_itoa(i, str);
+	return this->operator=(str);
+}
+
 template<size_t size>
 const BString<size> &BString<size>::operator=(const char *str) {
 	size_t strLen = ox_strlen(str) + 1;
@@ -76,6 +89,24 @@ const BString<size> &BString<size>::operator=(char *str) {
 	return *this = (const char*) str;
 }
 
+template<size_t size>
+const BString<size> &BString<size>::operator+=(const char *str) {
+	size_t strLen = ox_strlen(str) + 1;
+	auto currentSize = size();
+	if (cap() < currentSize + strLen) {
+		strLen = cap() - currentSize;
+	}
+	ox_memcpy(m_buff + currentSize, str, strLen);
+	// make sure last element is a null terminator
+	m_buff[cap() - 1] = 0;
+	return *this;
+}
+
+template<size_t size>
+const BString<size> &BString<size>::operator+=(char *str) {
+	return *this = (const char*) str;
+}
+
 template<size_t buffLen>
 bool BString<buffLen>::operator==(const BString<buffLen> &other) {
 	bool retval = true;
diff --git a/deps/ox/src/ox/std/strops.cpp b/deps/ox/src/ox/std/strops.cpp
index 2c0eccf7..4eeb8b4e 100644
--- a/deps/ox/src/ox/std/strops.cpp
+++ b/deps/ox/src/ox/std/strops.cpp
@@ -6,6 +6,8 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include "math.hpp"
+
 #include "strops.hpp"
 
 int ox_strcmp(const char *str1, const char *str2) {
@@ -89,3 +91,30 @@ int ox_atoi(const char *str) {
 
 	return total;
 }
+
+char *ox_itoa(int64_t v, char *str) {
+	auto mod = 1000000000000000000;
+	constexpr auto base = 10;
+	auto it = 0;
+	if (v < 0) {
+		str[it] = '-';
+		it++;
+	}
+	while (mod) {
+		auto digit = v / mod;
+		v %= mod;
+		mod /= base;
+		if (it or digit) {
+			int start;
+			if (digit < 10) {
+				start = '0';
+			} else {
+				start = 'a';
+				digit -= 10;
+			}
+			str[it] = start + digit;
+			it++;
+		}
+	}
+	return str;
+}
diff --git a/deps/ox/src/ox/std/strops.hpp b/deps/ox/src/ox/std/strops.hpp
index df01a507..58fcfd15 100644
--- a/deps/ox/src/ox/std/strops.hpp
+++ b/deps/ox/src/ox/std/strops.hpp
@@ -9,6 +9,7 @@
 #pragma once
 
 #include "types.hpp"
+#include "typetraits.hpp"
 
 int ox_strcmp(const char *str1, const char *str2);
 
@@ -25,3 +26,5 @@ int ox_lastIndexOf(const char *str, int character, int maxLen = 0xFFFFFFFF);
 int ox_lastIndexOf(char *str, int character, int maxLen = 0xFFFFFFFF);
 
 int ox_atoi(const char *str);
+
+char *ox_itoa(int64_t v, char *str);
diff --git a/deps/ox/src/ox/std/typetraits.hpp b/deps/ox/src/ox/std/typetraits.hpp
new file mode 100644
index 00000000..414df464
--- /dev/null
+++ b/deps/ox/src/ox/std/typetraits.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 - 2018 gtalent2@gmail.com
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "types.hpp"
+
+namespace ox {
+
+template<class T, T v>
+struct integral_constant {
+
+	using value_type = T;
+	using type = integral_constant;
+
+	static constexpr T value = v;
+
+	constexpr operator value_type() const noexcept {
+		return value;
+	}
+
+	constexpr value_type operator()() const noexcept {
+		return value;
+	}
+
+};
+
+using false_type = ox::integral_constant<bool, false>;
+using true_type = ox::integral_constant<bool, true>;
+
+
+// is_integral /////////////////////////////////////////////////////////////////
+
+template<typename T> struct is_integral: ox::false_type {};
+template<> struct is_integral<bool>    : ox::true_type {};
+template<> struct is_integral<wchar_t> : ox::true_type {};
+template<> struct is_integral<int8_t>  : ox::true_type {};
+template<> struct is_integral<uint8_t> : ox::true_type {};
+template<> struct is_integral<int16_t> : ox::true_type {};
+template<> struct is_integral<uint16_t>: ox::true_type {};
+template<> struct is_integral<int32_t> : ox::true_type {};
+template<> struct is_integral<uint32_t>: ox::true_type {};
+template<> struct is_integral<int64_t> : ox::true_type {};
+template<> struct is_integral<uint64_t>: ox::true_type {};
+
+
+// enable_if ///////////////////////////////////////////////////////////////////
+
+template<bool B, class T = void>
+struct enable_if {
+};
+
+template<class T>
+struct enable_if<true, T> {
+	using type = T;
+};
+
+};
diff --git a/deps/ox/src/ox/trace/trace.cpp b/deps/ox/src/ox/trace/trace.cpp
index 789349fe..2bd43239 100644
--- a/deps/ox/src/ox/trace/trace.cpp
+++ b/deps/ox/src/ox/trace/trace.cpp
@@ -6,24 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <stdarg.h>
-#include <stdio.h>
-
 #include <ox/std/std.hpp>
 
 #include "trace.hpp"
 
 namespace ox {
 
-struct TraceMsg {
-	const char *file;
-	int line;
-	uint64_t time;
-	const char *ch;
-	const char *msg;
-};
-
-void trace(const char *file, int line, const char *ch, const char *msg) {
+OutStream::OutStream(const char *file, int line, const char *ch, const char *msg) {
+	m_msg.file = file;
+	m_msg.line = line;
+	m_msg.ch = ch;
+	m_msg.msg = msg;
 }
 
 }
diff --git a/deps/ox/src/ox/trace/trace.hpp b/deps/ox/src/ox/trace/trace.hpp
index ce5ac8f2..73b652cb 100644
--- a/deps/ox/src/ox/trace/trace.hpp
+++ b/deps/ox/src/ox/trace/trace.hpp
@@ -8,10 +8,37 @@
 
 #pragma once
 
+#include <ox/std/std.hpp>
+
 namespace ox {
 
-void trace(const char *file, int line, const char *ch, const char *msg);
+struct TraceMsg {
+	const char *file;
+	int line;
+	uint64_t time;
+	const char *ch;
+	ox::BString<100> msg;
+};
+
+class OutStream {
+
+	private:
+		TraceMsg m_msg;
+
+	public:
+		OutStream() = default;
+
+		OutStream(const char *file, int line, const char *ch, const char *msg = "");
+
+		template<typename T>
+		OutStream &operator<<(T v) {
+			m_msg.msg += " ";
+			m_msg.msg += v;
+			return *this;
+		}
+
+};
 
 }
 
-#define ox_trace(ch, msg) ox::trace(__FILE__, __LINE__, ch, msg)
+#define oxTrace(ch, msg) ox::OutStream(__FILE__, __LINE__, ch, msg)