Some tweaks to Lua docs
[lsnes.git] / src / library / mathexpr-format.cpp
blobdc79ed0f0e1d5619b7f9e3bbe72fdc28bd300ff6
1 #include "mathexpr-format.hpp"
2 #include "string.hpp"
4 namespace
6 std::string pad(const std::string& orig, int width, bool zeropad, bool nosign)
8 std::string out = orig;
9 if(!nosign && (orig == "" || (orig[0] != '+' && orig[0] != '-')))
10 nosign = true;
11 if(nosign) {
12 while((int)out.length() < width)
13 out = (zeropad ? "0" : " ") + out;
14 } else {
15 if(zeropad)
16 while((int)out.length() < width)
17 out = out.substr(0,1) + "0" + out.substr(1);
18 else
19 while((int)out.length() < width)
20 out = " " + out;
22 return out;
25 std::string int_to_bits(uint64_t v)
27 if(v < 2) return std::string(1, 48 + v);
28 return int_to_bits(v >> 1) + std::string(1, 48 + (v & 1));
31 const char* numbers_l = "0123456789abcdef";
32 const char* numbers_u = "0123456789ABCDEF";
34 std::string print_decimals(double tail, unsigned base, int places, bool trimzero, bool uppercase)
36 std::string y;
37 for(int i = 0; i < places; i++) {
38 uint32_t n = floor(tail);
39 y += std::string(1, (uppercase ? numbers_u : numbers_l)[n % base]);
40 tail *= base;
41 tail = tail - n;
43 if(trimzero) {
44 size_t p = y.find_last_not_of("0");
45 if(p < y.length())
46 y = y.substr(0, p);
48 return y;
51 std::string format_float_base(double v, mathexpr_format fmt, unsigned base)
53 bool exponential = false;
54 std::string out;
55 char expsep = (base == 16) ? 'g' : 'e';
56 if(fmt.uppercasehex) expsep -= 32;
57 int exponent = 0;
58 v += 0.5 * pow(base, fmt.precision); //Round.
59 again:
60 out = "";
61 if(fmt.showsign || v < 0)
62 out += (v < 0) ? "-" : "+";
63 if(exponential) {
64 //TODO.
65 out += std::string(1, expsep);
66 out += (stringfmt() << exponent).str();
67 } else {
68 double vint = floor(v);
69 //TODO: Print whole part.
70 double tail = v - floor(v);
71 if(fmt.precision < 0) {
72 //Print up to 5 places.
73 std::string y = print_decimals(tail, base, fmt.precision, true, fmt.uppercasehex);
74 if(y != "")
75 out = out + "." + y;
76 } else if(fmt.precision > 0) {
77 //Print . and fmt.precision places.
78 out += ".";
79 out += print_decimals(tail, base, fmt.precision, false, fmt.uppercasehex);
82 if(!exponential && out.length() > fmt.width) {
83 exponential = true;
84 goto again;
88 std::string format_float_10(double v, mathexpr_format fmt)
90 std::string format;
91 format += "%";
92 if(fmt.showsign)
93 format += "+";
94 if(fmt.fillzeros)
95 format += "0";
96 if(fmt.width >= 0)
97 format += (stringfmt() << fmt.width).str();
98 if(fmt.precision >= 0)
99 format += (stringfmt() << "." << fmt.precision).str();
100 format += "g";
101 char buffer[256];
102 snprintf(buffer, sizeof(buffer) - 1, format.c_str(), v);
103 return buffer;
107 std::string math_format_bool(bool v, mathexpr_format fmt)
109 if(fmt.type == mathexpr_format::BOOLEAN)
110 return pad(v ? "true" : "false", fmt.width, false, true);
111 return math_format_unsigned(v ? 1 : 0, fmt);
114 std::string math_format_unsigned(uint64_t v, mathexpr_format fmt)
116 if(fmt.type == mathexpr_format::BOOLEAN)
117 return pad(v ? "true" : "false", fmt.width, false, true);
118 if(fmt.type == mathexpr_format::STRING)
119 return "<#Badformat>";
120 if(fmt.type == mathexpr_format::DEFAULT)
121 return (stringfmt() << v).str();
122 std::ostringstream _out;
123 switch(fmt.type) {
124 case mathexpr_format::BINARY:
125 _out << int_to_bits(v);
126 break;
127 case mathexpr_format::OCTAL:
128 _out << std::oct << v;
129 break;
130 case mathexpr_format::DECIMAL:
131 _out << v;
132 break;
133 case mathexpr_format::HEXADECIMAL:
134 if(fmt.uppercasehex) _out << std::uppercase;
135 _out << std::hex << v;
136 break;
138 std::string out = _out.str();
139 if(fmt.showsign)
140 out = "+" + out;
141 if(fmt.precision > 0) {
142 out += ".";
143 for(int i = 0; i < fmt.precision; i++)
144 out += "0";
146 return pad(out, fmt.width, fmt.fillzeros, false);
149 std::string math_format_signed(int64_t v, mathexpr_format fmt)
151 if(fmt.type == mathexpr_format::BOOLEAN)
152 return pad(v ? "true" : "false", fmt.width, false, true);
153 if(fmt.type == mathexpr_format::STRING)
154 return "<#Badformat>";
155 if(fmt.type == mathexpr_format::DEFAULT)
156 return (stringfmt() << v).str();
157 std::ostringstream _out;
158 switch(fmt.type) {
159 case mathexpr_format::BINARY:
160 if(v < 0) _out << "-";
161 _out << int_to_bits(std::abs(v));
162 break;
163 case mathexpr_format::OCTAL:
164 if(v < 0) _out << "-";
165 _out << std::oct << std::abs(v);
166 break;
167 case mathexpr_format::DECIMAL:
168 _out << v;
169 break;
170 case mathexpr_format::HEXADECIMAL:
171 if(v < 0) _out << "-";
172 if(fmt.uppercasehex) _out << std::uppercase;
173 _out << std::hex << std::abs(v);
174 break;
176 std::string out = _out.str();
177 if(fmt.showsign && v >= 0)
178 out = "+" + out;
179 if(fmt.precision > 0) {
180 out += ".";
181 for(int i = 0; i < fmt.precision; i++)
182 out += "0";
184 return pad(out, fmt.width, fmt.fillzeros, false);
187 std::string math_format_float(double v, mathexpr_format fmt)
189 if(fmt.type == mathexpr_format::BOOLEAN)
190 return pad(v ? "true" : "false", fmt.width, false, true);
191 if(fmt.type == mathexpr_format::STRING)
192 return "<#Badformat>";
193 if(fmt.type == mathexpr_format::DEFAULT)
194 return (stringfmt() << v).str();
195 std::string out;
196 switch(fmt.type) {
197 case mathexpr_format::BINARY:
198 //out = format_float_base(v, fmt, 2);
199 //break;
200 return "<#Badbase>";
201 case mathexpr_format::OCTAL:
202 //out = format_float_base(v, fmt, 8);
203 //break;
204 return "<#Badbase>";
205 case mathexpr_format::DECIMAL:
206 //out = format_float_base(v, fmt, 10);
207 out = format_float_10(v, fmt);
208 break;
209 case mathexpr_format::HEXADECIMAL:
210 //out = format_float_base(v, fmt, 16);
211 //break;
212 return "<#Badbase>";
214 return pad(out, fmt.width, fmt.fillzeros, false);
217 std::string math_format_complex(double vr, double vi, mathexpr_format fmt)
219 if(fmt.type == mathexpr_format::BOOLEAN)
220 return pad((vr || vi) ? "true" : "false", fmt.width, false, true);
221 if(fmt.type == mathexpr_format::STRING)
222 return "<#Badformat>";
223 if(fmt.type == mathexpr_format::DEFAULT) {
224 if(vi >= 0)
225 return (stringfmt() << vr << "+" << vi << "i").str();
226 else
227 return (stringfmt() << vr << vi << "i").str();
229 std::string xr = math_format_float(vr, fmt);
230 fmt.showsign = true;
231 std::string xi = math_format_float(vi, fmt);
232 return xr + xi + "i";
235 std::string math_format_string(std::string v, mathexpr_format fmt)
237 if(fmt.type == mathexpr_format::BOOLEAN)
238 return pad((v != "") ? "true" : "false", fmt.width, false, true);
239 if(fmt.type != mathexpr_format::STRING)
240 return "<#Badformat>";
241 if(fmt.precision > 0 && v.length() > fmt.precision)
242 v = v.substr(0, fmt.precision);
243 return pad(v, fmt.width, false, true);