1 #include "mathexpr-format.hpp"
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] != '-')))
14 while((int)out
.length() < width
)
15 out
= (zeropad
? "0" : " ") + out
;
18 while((int)out
.length() < width
)
19 out
= out
.substr(0,1) + "0" + out
.substr(1);
21 while((int)out
.length() < width
)
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
)
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
]);
46 size_t p
= y
.find_last_not_of("0");
53 std::string
format_float_base(double v
, _format fmt
, unsigned base
)
55 bool exponential
= false;
57 char expsep
= (base
== 16) ? 'g' : 'e';
58 if(fmt
.uppercasehex
) expsep
-= 32;
60 v
+= 0.5 * pow(base
, fmt
.precision
); //Round.
63 if(fmt
.showsign
|| v
< 0)
64 out
+= (v
< 0) ? "-" : "+";
67 out
+= std::string(1, expsep
);
68 out
+= (stringfmt() << exponent
).str();
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
);
77 } else if(fmt
.precision
> 0) {
78 //Print . and fmt.precision places.
80 out
+= print_decimals(tail
, base
, fmt
.precision
, false, fmt
.uppercasehex
);
83 if(!exponential
&& (ssize_t
)out
.length() > fmt
.width
) {
90 std::string
format_float_10(double v
, _format fmt
)
99 format
+= (stringfmt() << fmt
.width
).str();
100 if(fmt
.precision
>= 0)
101 format
+= (stringfmt() << "." << fmt
.precision
).str();
104 snprintf(buffer
, sizeof(buffer
) - 1, format
.c_str(), v
);
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
;
126 case _format::BINARY
:
127 _out
<< int_to_bits(v
);
130 _out
<< std::oct
<< v
;
132 case _format::DECIMAL
:
135 case _format::HEXADECIMAL
:
136 if(fmt
.uppercasehex
) _out
<< std::uppercase
;
137 _out
<< std::hex
<< v
;
139 case _format::BOOLEAN
:
140 case _format::STRING
:
141 case _format::DEFAULT
:
144 std::string out
= _out
.str();
147 if(fmt
.precision
> 0) {
149 for(int i
= 0; i
< fmt
.precision
; i
++)
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
;
165 case _format::BINARY
:
166 if(v
< 0) _out
<< "-";
167 _out
<< int_to_bits(std::abs(v
));
170 if(v
< 0) _out
<< "-";
171 _out
<< std::oct
<< std::abs(v
);
173 case _format::DECIMAL
:
176 case _format::HEXADECIMAL
:
177 if(v
< 0) _out
<< "-";
178 if(fmt
.uppercasehex
) _out
<< std::uppercase
;
179 _out
<< std::hex
<< std::abs(v
);
181 case _format::BOOLEAN
:
182 case _format::STRING
:
183 case _format::DEFAULT
:
186 std::string out
= _out
.str();
187 if(fmt
.showsign
&& v
>= 0)
189 if(fmt
.precision
> 0) {
191 for(int i
= 0; i
< fmt
.precision
; i
++)
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();
207 case _format::BINARY
:
208 //out = format_float_base(v, fmt, 2);
212 //out = format_float_base(v, fmt, 8);
215 case _format::DECIMAL
:
216 //out = format_float_base(v, fmt, 10);
217 out
= format_float_10(v
, fmt
);
219 case _format::HEXADECIMAL
:
220 //out = format_float_base(v, fmt, 16);
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
) {
239 return (stringfmt() << vr
<< "+" << vi
<< "i").str();
241 return (stringfmt() << vr
<< vi
<< "i").str();
243 std::string xr
= format_float(vr
, fmt
);
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);