diff options
Diffstat (limited to 'src/common/pretty_binary.cc')
-rw-r--r-- | src/common/pretty_binary.cc | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/common/pretty_binary.cc b/src/common/pretty_binary.cc new file mode 100644 index 000000000..d58b0fb6e --- /dev/null +++ b/src/common/pretty_binary.cc @@ -0,0 +1,95 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "pretty_binary.h" +#include <stdexcept> +#include <sstream> + +std::string pretty_binary_string_reverse(const std::string& pretty) +{ + size_t i = 0; + auto raise = [&](size_t failpos) { + std::ostringstream ss; + ss << "invalid char at pos " << failpos << " of " << pretty; + throw std::invalid_argument(ss.str()); + }; + auto hexdigit = [&](unsigned char c) -> int32_t { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; + }; + auto require = [&](unsigned char c) { + if (i >= pretty.length() || pretty[i] != c) { + raise(i); + } + ++i; + }; + std::string bin; + if (pretty.empty()) + return bin; + bin.reserve(pretty.length()); + bool strmode; + switch (pretty[0]) { + case '\'': + ++i; + strmode = true; + break; + case '0': + ++i; + require('x'); + if (i == pretty.length()) { + raise(i); + } + strmode = false; + break; + default: + raise(0); + } + for (; i < pretty.length();) { + if (strmode) { + if (pretty[i] == '\'') { + if (i + 1 < pretty.length() && pretty[i + 1] == '\'') { + bin.push_back('\''); + i += 2; + } else { + ++i; + strmode = false; + if (i + 1 < pretty.length()) { + require('0'); + require('x'); + if (i == pretty.length()) { + raise(i); + } + } + } + } else { + bin.push_back(pretty[i]); + ++i; + } + } else { + if (pretty[i] != '\'') { + int32_t hex0 = hexdigit(pretty[i]); + if (hex0 < 0) { + raise(i); + } + ++i; + if (i >= pretty.length()) { + raise(i); + } + int32_t hex1 = hexdigit(pretty[i]); + if (hex1 < 0) { + raise(i); + } + bin.push_back(hex0 * 0x10 + hex1); + ++i; + } else { + strmode = true; + ++i; + } + } + } + if (strmode) + raise(i); + return bin; +} |