Namespacify mathexpr
[lsnes.git] / src / library / mathexpr-format.cpp
blob748d414bed069e89b497ffce92fb90fbbc61b724
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 const char* numbers_l = "0123456789abcdef";
34 const char* numbers_u = "0123456789ABCDEF";
36 std::string print_decimals(double tail, unsigned base, int places, bool trimzero, bool uppercase)
38 std::string y;
39 for(int i = 0; i < places; i++) {
40 uint32_t n = floor(tail);
41 y += std::string(1, (uppercase ? numbers_u : numbers_l)[n % base]);
42 tail *= base;
43 tail = tail - n;
45 if(trimzero) {
46 size_t p = y.find_last_not_of("0");
47 if(p < y.length())
48 y = y.substr(0, p);
50 return y;
53 std::string format_float_base(double v, _format fmt, unsigned base)
55 bool exponential = false;
56 std::string out;
57 char expsep = (base == 16) ? 'g' : 'e';
58 if(fmt.uppercasehex) expsep -= 32;
59 int exponent = 0;
60 v += 0.5 * pow(base, fmt.precision); //Round.
61 again:
62 out = "";
63 if(fmt.showsign || v < 0)
64 out += (v < 0) ? "-" : "+";
65 if(exponential) {
66 //TODO.
67 out += std::string(1, expsep);
68 out += (stringfmt() << exponent).str();
69 } else {
70 //TODO: Print whole part.
71 double tail = v - floor(v);
72 if(fmt.precision < 0) {
73 //Print up to 5 places.
74 std::string y = print_decimals(tail, base, fmt.precision, true, fmt.uppercasehex);
75 if(y != "")
76 out = out + "." + y;
77 } else if(fmt.precision > 0) {
78 //Print . and fmt.precision places.
79 out += ".";
80 out += print_decimals(tail, base, fmt.precision, false, fmt.uppercasehex);
83 if(!exponential && (ssize_t)out.length() > fmt.width) {
84 exponential = true;
85 goto again;
87 return out;
90 std::string format_float_10(double v, _format fmt)
92 std::string format;
93 format += "%";
94 if(fmt.showsign)
95 format += "+";
96 if(fmt.fillzeros)
97 format += "0";
98 if(fmt.width >= 0)
99 format += (stringfmt() << fmt.width).str();
100 if(fmt.precision >= 0)
101 format += (stringfmt() << "." << fmt.precision).str();
102 format += "g";
103 char buffer[256];
104 snprintf(buffer, sizeof(buffer) - 1, format.c_str(), v);
105 return buffer;
109 std::string format_bool(bool v, _format fmt)
111 if(fmt.type == _format::BOOLEAN)
112 return pad(v ? "true" : "false", fmt.width, false, true);
113 return format_unsigned(v ? 1 : 0, fmt);
116 std::string format_unsigned(uint64_t v, _format fmt)
118 if(fmt.type == _format::BOOLEAN)
119 return pad(v ? "true" : "false", fmt.width, false, true);
120 if(fmt.type == _format::STRING)
121 return "<#Badformat>";
122 if(fmt.type == _format::DEFAULT)
123 return (stringfmt() << v).str();
124 std::ostringstream _out;
125 switch(fmt.type) {
126 case _format::BINARY:
127 _out << int_to_bits(v);
128 break;
129 case _format::OCTAL:
130 _out << std::oct << v;
131 break;
132 case _format::DECIMAL:
133 _out << v;
134 break;
135 case _format::HEXADECIMAL:
136 if(fmt.uppercasehex) _out << std::uppercase;
137 _out << std::hex << v;
138 break;
139 case _format::BOOLEAN:
140 case _format::STRING:
141 case _format::DEFAULT:
144 std::string out = _out.str();
145 if(fmt.showsign)
146 out = "+" + out;
147 if(fmt.precision > 0) {
148 out += ".";
149 for(int i = 0; i < fmt.precision; i++)
150 out += "0";
152 return pad(out, fmt.width, fmt.fillzeros, false);
155 std::string format_signed(int64_t v, _format fmt)
157 if(fmt.type == _format::BOOLEAN)
158 return pad(v ? "true" : "false", fmt.width, false, true);
159 if(fmt.type == _format::STRING)
160 return "<#Badformat>";
161 if(fmt.type == _format::DEFAULT)
162 return (stringfmt() << v).str();
163 std::ostringstream _out;
164 switch(fmt.type) {
165 case _format::BINARY:
166 if(v < 0) _out << "-";
167 _out << int_to_bits(std::abs(v));
168 break;
169 case _format::OCTAL:
170 if(v < 0) _out << "-";
171 _out << std::oct << std::abs(v);
172 break;
173 case _format::DECIMAL:
174 _out << v;
175 break;
176 case _format::HEXADECIMAL:
177 if(v < 0) _out << "-";
178 if(fmt.uppercasehex) _out << std::uppercase;
179 _out << std::hex << std::abs(v);
180 break;
181 case _format::BOOLEAN:
182 case _format::STRING:
183 case _format::DEFAULT:
186 std::string out = _out.str();
187 if(fmt.showsign && v >= 0)
188 out = "+" + out;
189 if(fmt.precision > 0) {
190 out += ".";
191 for(int i = 0; i < fmt.precision; i++)
192 out += "0";
194 return pad(out, fmt.width, fmt.fillzeros, false);
197 std::string format_float(double v, _format fmt)
199 if(fmt.type == _format::BOOLEAN)
200 return pad(v ? "true" : "false", fmt.width, false, true);
201 if(fmt.type == _format::STRING)
202 return "<#Badformat>";
203 if(fmt.type == _format::DEFAULT)
204 return (stringfmt() << v).str();
205 std::string out;
206 switch(fmt.type) {
207 case _format::BINARY:
208 //out = format_float_base(v, fmt, 2);
209 //break;
210 return "<#Badbase>";
211 case _format::OCTAL:
212 //out = format_float_base(v, fmt, 8);
213 //break;
214 return "<#Badbase>";
215 case _format::DECIMAL:
216 //out = format_float_base(v, fmt, 10);
217 out = format_float_10(v, fmt);
218 break;
219 case _format::HEXADECIMAL:
220 //out = format_float_base(v, fmt, 16);
221 //break;
222 return "<#Badbase>";
223 case _format::BOOLEAN:
224 case _format::STRING:
225 case _format::DEFAULT:
228 return pad(out, fmt.width, fmt.fillzeros, false);
231 std::string format_complex(double vr, double vi, _format fmt)
233 if(fmt.type == _format::BOOLEAN)
234 return pad((vr || vi) ? "true" : "false", fmt.width, false, true);
235 if(fmt.type == _format::STRING)
236 return "<#Badformat>";
237 if(fmt.type == _format::DEFAULT) {
238 if(vi >= 0)
239 return (stringfmt() << vr << "+" << vi << "i").str();
240 else
241 return (stringfmt() << vr << vi << "i").str();
243 std::string xr = format_float(vr, fmt);
244 fmt.showsign = true;
245 std::string xi = format_float(vi, fmt);
246 return xr + xi + "i";
249 std::string format_string(std::string v, _format fmt)
251 if(fmt.type == _format::BOOLEAN)
252 return pad((v != "") ? "true" : "false", fmt.width, false, true);
253 if(fmt.type != _format::STRING)
254 return "<#Badformat>";
255 if(fmt.precision > 0 && (ssize_t)v.length() > fmt.precision)
256 v = v.substr(0, fmt.precision);
257 return pad(v, fmt.width, false, true);