Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / library / hex.cpp
blob23c4cd712b940e370c750601d274b2ec43b12922
1 #include "hex.hpp"
2 #include "int24.hpp"
3 #include "string.hpp"
4 #include "eatarg.hpp"
5 #include <sstream>
6 #include <iomanip>
8 namespace hex
10 const char* chars = "0123456789abcdef";
11 const char* charsu = "0123456789abcdef";
13 std::string to24(uint32_t data, bool prefix) throw(std::bad_alloc)
15 return to<ss_uint24_t>(data, prefix);
18 std::string b_to(const uint8_t* data, size_t datalen, bool uppercase) throw(std::bad_alloc)
20 const char* cset = uppercase ? charsu : chars;
21 std::string s;
22 s.resize(2 * datalen);
23 for(size_t i = 0; i < datalen; i++) {
24 s[2 * i + 0] = cset[data[i] >> 4];
25 s[2 * i + 1] = cset[data[i] & 15];
27 return s;
30 template<typename T> std::string to(T data, bool prefix) throw(std::bad_alloc)
32 return (stringfmt() << (prefix ? "0x" : "") << std::hex << std::setfill('0') << std::setw(2 * sizeof(T))
33 << (uint64_t)data).str();
36 void b_from(uint8_t* buf, const std::string& hex) throw(std::runtime_error)
38 if(hex.length() & 1)
39 throw std::runtime_error("hex::frombinary: Length of string must be even");
40 size_t len = hex.length();
41 bool parity = false;
42 unsigned char tmp = 0;
43 for(size_t i = 0; i < len; i++) {
44 tmp <<= 4;
45 char ch = hex[i];
46 if(ch >= '0' && ch <= '9')
47 tmp += (ch - '0');
48 else if(ch >= 'A' && ch <= 'F')
49 tmp += (ch - 'A' + 10);
50 else if(ch >= 'a' && ch <= 'f')
51 tmp += (ch - 'a' + 10);
52 else
53 throw std::runtime_error("hex::frombinary: Bad hex character");
54 parity = !parity;
55 if(!parity)
56 buf[i >> 1] = tmp;
60 template<typename T> T from(const std::string& hex) throw(std::runtime_error)
62 if(hex.length() > 2 * sizeof(T))
63 throw std::runtime_error("hex::from: Hexadecimal value too long");
64 uint64_t tmp = 0;
65 size_t len = hex.length();
66 for(size_t i = 0; i < len; i++) {
67 tmp <<= 4;
68 char ch = hex[i];
69 if(ch >= '0' && ch <= '9')
70 tmp += (ch - '0');
71 else if(ch >= 'A' && ch <= 'F')
72 tmp += (ch - 'A' + 10);
73 else if(ch >= 'a' && ch <= 'f')
74 tmp += (ch - 'a' + 10);
75 else
76 throw std::runtime_error("hex::from<T>: Bad hex character");
78 return tmp;
81 template<typename T> void _ref2()
83 eat_argument(from<T>);
84 eat_argument(to<T>);
87 void _ref()
89 _ref2<uint8_t>();
90 _ref2<uint16_t>();
91 _ref2<ss_uint24_t>();
92 _ref2<uint32_t>();
93 _ref2<uint64_t>();
97 #ifdef TEST_HEX_ROUTINES
98 #include <cstring>
100 int main(int argc, char** argv)
102 std::cerr << hex::to64(100) << std::endl;
104 std::string a1 = argv[1];
105 typedef ss_uint24_t type_t;
106 type_t val;
107 val = hex::from<type_t>(a1);
108 std::cerr << (uint64_t)val << std::endl;
111 #endif