1 #include "mathexpr-format.hpp"
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] != '-')))
12 while((int)out
.length() < width
)
13 out
= (zeropad
? "0" : " ") + out
;
16 while((int)out
.length() < width
)
17 out
= out
.substr(0,1) + "0" + out
.substr(1);
19 while((int)out
.length() < width
)
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
)
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
]);
44 size_t p
= y
.find_last_not_of("0");
51 std::string
format_float_base(double v
, mathexpr_format fmt
, unsigned base
)
53 bool exponential
= false;
55 char expsep
= (base
== 16) ? 'g' : 'e';
56 if(fmt
.uppercasehex
) expsep
-= 32;
58 v
+= 0.5 * pow(base
, fmt
.precision
); //Round.
61 if(fmt
.showsign
|| v
< 0)
62 out
+= (v
< 0) ? "-" : "+";
65 out
+= std::string(1, expsep
);
66 out
+= (stringfmt() << exponent
).str();
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
);
76 } else if(fmt
.precision
> 0) {
77 //Print . and fmt.precision places.
79 out
+= print_decimals(tail
, base
, fmt
.precision
, false, fmt
.uppercasehex
);
82 if(!exponential
&& out
.length() > fmt
.width
) {
88 std::string
format_float_10(double v
, mathexpr_format fmt
)
97 format
+= (stringfmt() << fmt
.width
).str();
98 if(fmt
.precision
>= 0)
99 format
+= (stringfmt() << "." << fmt
.precision
).str();
102 snprintf(buffer
, sizeof(buffer
) - 1, format
.c_str(), v
);
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
;
124 case mathexpr_format::BINARY
:
125 _out
<< int_to_bits(v
);
127 case mathexpr_format::OCTAL
:
128 _out
<< std::oct
<< v
;
130 case mathexpr_format::DECIMAL
:
133 case mathexpr_format::HEXADECIMAL
:
134 if(fmt
.uppercasehex
) _out
<< std::uppercase
;
135 _out
<< std::hex
<< v
;
138 std::string out
= _out
.str();
141 if(fmt
.precision
> 0) {
143 for(int i
= 0; i
< fmt
.precision
; i
++)
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
;
159 case mathexpr_format::BINARY
:
160 if(v
< 0) _out
<< "-";
161 _out
<< int_to_bits(std::abs(v
));
163 case mathexpr_format::OCTAL
:
164 if(v
< 0) _out
<< "-";
165 _out
<< std::oct
<< std::abs(v
);
167 case mathexpr_format::DECIMAL
:
170 case mathexpr_format::HEXADECIMAL
:
171 if(v
< 0) _out
<< "-";
172 if(fmt
.uppercasehex
) _out
<< std::uppercase
;
173 _out
<< std::hex
<< std::abs(v
);
176 std::string out
= _out
.str();
177 if(fmt
.showsign
&& v
>= 0)
179 if(fmt
.precision
> 0) {
181 for(int i
= 0; i
< fmt
.precision
; i
++)
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();
197 case mathexpr_format::BINARY
:
198 //out = format_float_base(v, fmt, 2);
201 case mathexpr_format::OCTAL
:
202 //out = format_float_base(v, fmt, 8);
205 case mathexpr_format::DECIMAL
:
206 //out = format_float_base(v, fmt, 10);
207 out
= format_float_10(v
, fmt
);
209 case mathexpr_format::HEXADECIMAL
:
210 //out = format_float_base(v, fmt, 16);
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
) {
225 return (stringfmt() << vr
<< "+" << vi
<< "i").str();
227 return (stringfmt() << vr
<< vi
<< "i").str();
229 std::string xr
= math_format_float(vr
, fmt
);
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);