Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / library / mathexpr-format.cpp
blobce32588c6ac66d843b63c1ab874ca66ea59e05aa
1 #include "mathexpr-format.hpp"
2 #include "string.hpp"
4 namespace mathexpr
6 namespace
8 std::string pad(const std::string& orig, int width, bool zeropad, bool nosign)
10 std::string out = orig;
11 if(!nosign && (orig == "" || (orig[0] != '+' && orig[0] != '-')))
12 nosign = true;
13 if(nosign) {
14 while((int)out.length() < width)
15 out = (zeropad ? "0" : " ") + out;
16 } else {
17 if(zeropad)
18 while((int)out.length() < width)
19 out = out.substr(0,1) + "0" + out.substr(1);
20 else
21 while((int)out.length() < width)
22 out = " " + out;
24 return out;
27 std::string int_to_bits(uint64_t v)
29 if(v < 2) return std::string(1, 48 + v);
30 return int_to_bits(v >> 1) + std::string(1, 48 + (v & 1));
33 std::string format_float_10(double v, _format fmt)
35 std::string format;
36 format += "%";
37 if(fmt.showsign)
38 format += "+";
39 if(fmt.fillzeros)
40 format += "0";
41 if(fmt.width >= 0)
42 format += (stringfmt() << fmt.width).str();
43 if(fmt.precision >= 0)
44 format += (stringfmt() << "." << fmt.precision).str();
45 format += "g";
46 char buffer[256];
47 snprintf(buffer, sizeof(buffer) - 1, format.c_str(), v);
48 return buffer;
52 std::string format_bool(bool v, _format fmt)
54 if(fmt.type == _format::BOOLEAN)
55 return pad(v ? "true" : "false", fmt.width, false, true);
56 return format_unsigned(v ? 1 : 0, fmt);
59 std::string format_unsigned(uint64_t v, _format fmt)
61 if(fmt.type == _format::BOOLEAN)
62 return pad(v ? "true" : "false", fmt.width, false, true);
63 if(fmt.type == _format::STRING)
64 return "<#Badformat>";
65 if(fmt.type == _format::DEFAULT)
66 return (stringfmt() << v).str();
67 std::ostringstream _out;
68 switch(fmt.type) {
69 case _format::BINARY:
70 _out << int_to_bits(v);
71 break;
72 case _format::OCTAL:
73 _out << std::oct << v;
74 break;
75 case _format::DECIMAL:
76 _out << v;
77 break;
78 case _format::HEXADECIMAL:
79 if(fmt.uppercasehex) _out << std::uppercase;
80 _out << std::hex << v;
81 break;
82 case _format::BOOLEAN:
83 case _format::STRING:
84 case _format::DEFAULT:
87 std::string out = _out.str();
88 if(fmt.showsign)
89 out = "+" + out;
90 if(fmt.precision > 0) {
91 out += ".";
92 for(int i = 0; i < fmt.precision; i++)
93 out += "0";
95 return pad(out, fmt.width, fmt.fillzeros, false);
98 std::string format_signed(int64_t v, _format fmt)
100 if(fmt.type == _format::BOOLEAN)
101 return pad(v ? "true" : "false", fmt.width, false, true);
102 if(fmt.type == _format::STRING)
103 return "<#Badformat>";
104 if(fmt.type == _format::DEFAULT)
105 return (stringfmt() << v).str();
106 std::ostringstream _out;
107 switch(fmt.type) {
108 case _format::BINARY:
109 if(v < 0) _out << "-";
110 _out << int_to_bits(std::abs(v));
111 break;
112 case _format::OCTAL:
113 if(v < 0) _out << "-";
114 _out << std::oct << std::abs(v);
115 break;
116 case _format::DECIMAL:
117 _out << v;
118 break;
119 case _format::HEXADECIMAL:
120 if(v < 0) _out << "-";
121 if(fmt.uppercasehex) _out << std::uppercase;
122 _out << std::hex << std::abs(v);
123 break;
124 case _format::BOOLEAN:
125 case _format::STRING:
126 case _format::DEFAULT:
129 std::string out = _out.str();
130 if(fmt.showsign && v >= 0)
131 out = "+" + out;
132 if(fmt.precision > 0) {
133 out += ".";
134 for(int i = 0; i < fmt.precision; i++)
135 out += "0";
137 return pad(out, fmt.width, fmt.fillzeros, false);
140 std::string format_float(double v, _format fmt)
142 if(fmt.type == _format::BOOLEAN)
143 return pad(v ? "true" : "false", fmt.width, false, true);
144 if(fmt.type == _format::STRING)
145 return "<#Badformat>";
146 if(fmt.type == _format::DEFAULT)
147 return (stringfmt() << v).str();
148 std::string out;
149 switch(fmt.type) {
150 case _format::BINARY:
151 //out = format_float_base(v, fmt, 2);
152 //break;
153 return "<#Badbase>";
154 case _format::OCTAL:
155 //out = format_float_base(v, fmt, 8);
156 //break;
157 return "<#Badbase>";
158 case _format::DECIMAL:
159 //out = format_float_base(v, fmt, 10);
160 out = format_float_10(v, fmt);
161 break;
162 case _format::HEXADECIMAL:
163 //out = format_float_base(v, fmt, 16);
164 //break;
165 return "<#Badbase>";
166 case _format::BOOLEAN:
167 case _format::STRING:
168 case _format::DEFAULT:
171 return pad(out, fmt.width, fmt.fillzeros, false);
174 std::string format_complex(double vr, double vi, _format fmt)
176 if(fmt.type == _format::BOOLEAN)
177 return pad((vr || vi) ? "true" : "false", fmt.width, false, true);
178 if(fmt.type == _format::STRING)
179 return "<#Badformat>";
180 if(fmt.type == _format::DEFAULT) {
181 if(vi >= 0)
182 return (stringfmt() << vr << "+" << vi << "i").str();
183 else
184 return (stringfmt() << vr << vi << "i").str();
186 std::string xr = format_float(vr, fmt);
187 fmt.showsign = true;
188 std::string xi = format_float(vi, fmt);
189 return xr + xi + "i";
192 std::string format_string(std::string v, _format fmt)
194 if(fmt.type == _format::BOOLEAN)
195 return pad((v != "") ? "true" : "false", fmt.width, false, true);
196 if(fmt.type != _format::STRING)
197 return "<#Badformat>";
198 if(fmt.precision > 0 && (ssize_t)v.length() > fmt.precision)
199 v = v.substr(0, fmt.precision);
200 return pad(v, fmt.width, false, true);