summaryrefslogtreecommitdiff
path: root/binparse
diff options
context:
space:
mode:
Diffstat (limited to 'binparse')
-rw-r--r--binparse/CMakeLists.txt1
-rw-r--r--binparse/otreestream.cpp47
-rw-r--r--binparse/otreestream.hpp42
-rw-r--r--binparse/output.hpp33
-rw-r--r--binparse/types.hpp5
5 files changed, 127 insertions, 1 deletions
diff --git a/binparse/CMakeLists.txt b/binparse/CMakeLists.txt
index cbc83b5..c41a2b5 100644
--- a/binparse/CMakeLists.txt
+++ b/binparse/CMakeLists.txt
@@ -3,6 +3,7 @@ add_library(binparse STATIC
types.hpp
parse.hpp parse.cpp
output.hpp output.cpp
+ otreestream.hpp otreestream.cpp
)
target_include_directories(binparse
diff --git a/binparse/otreestream.cpp b/binparse/otreestream.cpp
new file mode 100644
index 0000000..a93c0e9
--- /dev/null
+++ b/binparse/otreestream.cpp
@@ -0,0 +1,47 @@
+#include "otreestream.hpp"
+
+namespace binparse {
+
+int treebuf::sync() {
+ return this->sbuf->pubsync();
+}
+
+int treebuf::overflow(int c) {
+ if (c != std::char_traits<char>::eof()) {
+ if (this->need_prefix && !this->prefix.empty() && this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
+ return std::char_traits<char>::eof();
+ }
+ this->need_prefix = c == '\n';
+ }
+ return this->sbuf->sputc(c);
+}
+
+treebuf::treebuf(std::streambuf* sbuf)
+: sbuf(sbuf)
+, need_prefix(true)
+{}
+
+void treebuf::indent() {
+ prefix += "\t";
+}
+
+void treebuf::unindent() {
+ prefix = std::string(prefix.begin(), prefix.end()-1);
+}
+
+otreestream::otreestream(std::ostream& out)
+: treebuf(out.rdbuf())
+, std::ios(static_cast<std::streambuf*>(this))
+, std::ostream(static_cast<std::streambuf*>(this)) {
+}
+
+indent::indent(std::ostream& os)
+: tb(dynamic_cast<treebuf&>(os)) {
+ tb.indent();
+}
+
+indent::~indent() {
+ tb.unindent();
+}
+
+}
diff --git a/binparse/otreestream.hpp b/binparse/otreestream.hpp
new file mode 100644
index 0000000..3f57d4e
--- /dev/null
+++ b/binparse/otreestream.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <streambuf>
+#include <string>
+#include <ostream>
+
+namespace binparse {
+
+class treebuf : public std::streambuf
+{
+ std::string prefix;
+ std::streambuf* sbuf;
+ bool need_prefix;
+
+ int sync();
+ int overflow(int c);
+
+public:
+ treebuf(std::streambuf* sbuf);
+
+ void indent();
+
+ void unindent();
+};
+
+class otreestream : public virtual treebuf, public std::ostream
+{
+public:
+ otreestream(std::ostream& out);
+};
+
+class indent {
+
+ treebuf& tb;
+
+public:
+ indent(std::ostream& os);
+
+ ~indent();
+};
+
+} \ No newline at end of file
diff --git a/binparse/output.hpp b/binparse/output.hpp
index b16dd89..705a380 100644
--- a/binparse/output.hpp
+++ b/binparse/output.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "types.hpp"
+#include "otreestream.hpp"
#include "index_list.hpp"
@@ -10,6 +11,8 @@
#include <array>
#include <vector>
+#include <map>
+#include <streambuf>
namespace binparse {
@@ -36,6 +39,24 @@ std::ostream& operator<<(std::ostream& os, std::vector<uint8_t> vec);
template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = nullptr>
std::ostream& operator<<(std::ostream&, T const&);
+template <typename Key, typename Value>
+std::ostream& operator<<(std::ostream& os, std::map<Key, Value> const& map) {
+ try {
+ indent scoped(os);
+ os << std::endl;
+ for(auto&& entry : map) {
+ os << entry.first << ": " << entry.second << std::endl;
+ }
+ } catch(std::exception&) {
+ os << std::endl;
+ for(auto&& entry : map) {
+ os << entry.first << ": " << entry.second << std::endl;
+ }
+ }
+
+ return os;
+}
+
template<typename T>
std::ostream& output_impl(std::ostream& os, T const&, indices<>) {
return os;
@@ -43,15 +64,25 @@ std::ostream& output_impl(std::ostream& os, T const&, indices<>) {
template <typename T, int I, int... Indices>
std::ostream& output_impl(std::ostream& os, T const& t, indices<I, Indices...>) {
+
os << boost::fusion::extension::struct_member_name<T, I>::call() << ": " << boost::fusion::at_c<I>(t) << std::endl;
return output_impl(os, t, indices<Indices...>{});
+
}
template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type*>
std::ostream& operator<<(std::ostream& os, T const& t) {
typedef typename build_indices<boost::fusion::result_of::size<T>::value>::type indices;
- return output_impl<T>(os, t, indices{});
+ try {
+ indent scoped(os);
+ os << std::endl;
+ output_impl<T>(os, t, indices{});
+ } catch(std::exception&) {
+ os << std::endl;
+ output_impl<T>(os, t, indices{});
+ }
+ return os;
}
} \ No newline at end of file
diff --git a/binparse/types.hpp b/binparse/types.hpp
index e92a7a6..9b6c4a6 100644
--- a/binparse/types.hpp
+++ b/binparse/types.hpp
@@ -17,4 +17,9 @@ BOOST_STRONG_TYPEDEF(uint16_t, Value16)
BOOST_STRONG_TYPEDEF(uint32_t, Offset32)
BOOST_STRONG_TYPEDEF(uint32_t, Value32)
+template <typename T>
+T operator+(T const lh, T const rh) {
+ return T(0 + lh + rh);
+}
+
} \ No newline at end of file