159 {
161
164 fmtStr = fmtStr.
sub(1);
165 }
168 fmtStr = fmtStr.
sub(2);
169 }
170
172 opts.capitalE = true;
173 fmtStr = fmtStr.
sub(1);
174 }
176 opts.capitalE = false;
177 fmtStr = fmtStr.
sub(1);
178 }
179
181 opts.capitalE = true;
182 opts.forceScientific = true;
183 fmtStr = fmtStr.
sub(1);
184 }
186 opts.forceScientific = true;
187 fmtStr = fmtStr.
sub(1);
188 }
189
191 opts.plusE = true;
192 fmtStr = fmtStr.
sub(1);
193 }
194
197 const auto decSpecifier = fmtStr.sub(pivot + 1);
198 ensure(!decSpecifier.empty(),
"Invalid format string");
199
200 const auto sepIndex =
slices::first_index(
'-', decSpecifier).value_or(decSpecifier.size());
201 const auto minDigits = decSpecifier.sub(0, sepIndex);
202 ensure(!minDigits.empty(),
"Invalid format string");
203
205 ensure(opts.minDecPlaces >= 0);
206
207 opts.maxDecPlaces = opts.minDecPlaces;
208 if (const auto maxDigits = decSpecifier.sub(sepIndex + 1); !maxDigits.empty()) {
210 ensure(opts.maxDecPlaces >= opts.minDecPlaces);
211 ensure(opts.maxDecPlaces <= 16);
212 }
213
214 fmtStr = fmtStr.
sub(0, pivot);
215
216 if (opts.maxDecPlaces <= 16) {
218 f *= b;
219 f = std::round(f);
220 f /= b;
221 }
222 }
223
226 fmtStr = fmtStr.
sub(fmtStr.size());
227 }
228
229
230 ensure(fmtStr.empty(),
"Invalid format string");
231 ensure(opts.precision <= 16);
232 auto b = std::array<char, 100>{};
234 auto printRes =
to_chars(buff, f, opts);
235 if (printRes.is_error()) {
237 return error(Err::OUT_OF_ROOM);
238 }
239
240 if (opts.minDecPlaces == 0 &&
static_cast<size_t>(opts.maxDecPlaces) >= printRes.value().
size()) {
241 return writer.write_all(printRes.value()).with_success_val(printRes.value().size());
242 }
243 else {
244 auto raw = printRes.value().to_const();
246 return writer.write_all(printRes.value()).with_success_val(printRes.value().size());
247 }
248
250 if (decPointIndex.empty()) {
251 if (opts.minDecPlaces == 0) {
252 return writer.write_all(printRes.value()).with_success_val(printRes.value().size());
253 }
254
255 size_t written = 0;
256
259
260 auto end = raw.size();
261
262 if (sciNoteLowerE.has_value()) {
263 end = sciNoteLowerE.value();
264 }
265 else if (sciNoteUpperE.has_value()) {
266 end = sciNoteUpperE.value();
267 }
268
269 auto toPrint = raw.sub(0, end);
270
271 if (
auto r =
writer.write_all(toPrint); r.is_error()) {
272 return r.error();
273 }
274 written += toPrint.size();
275
276 if (
auto r =
writer.write(
'.'); r.is_error()) {
277 return r.error();
278 }
279 ++written;
280
281 if (
auto r =
writer.write_n_times(
'0',
static_cast<size_t>(opts.minDecPlaces)); r.is_error()) {
282 return r.error();
283 }
284 written += opts.minDecPlaces;
285 auto rest = raw.
sub(end);
286 if (!rest.empty()) {
287 if (
auto r =
writer.write_all(rest); r.is_error()) {
288 return r.error();
289 }
290 written += rest.size();
291 }
292
294 }
295 else {
296 auto end = raw.size();
299
300 if (sciNoteLowerE.has_value()) {
301 end = sciNoteLowerE.value();
302 }
303 else if (sciNoteUpperE.has_value()) {
304 end = sciNoteUpperE.value();
305 }
306
307 auto decs = raw.sub(0, end).sub(decPointIndex.value() + 1);
308 auto numDigits = decs.size();
309 if (
static_cast<i32>(numDigits) >= opts.minDecPlaces &&
static_cast<i32>(numDigits) <= opts.maxDecPlaces) {
310 return writer.write_all(printRes.value()).with_success_val(printRes.value().size());
311 }
312
313 auto start = raw.sub(0, decPointIndex.value() + 1);
314 size_t written = 0;
315
316 if (
auto r =
writer.write_all(start); r.is_error()) {
317 return r.error();
318 }
319 written += start.size();
320
321 if (
static_cast<i32>(numDigits) < opts.minDecPlaces) {
322 if (
auto r =
writer.write_all(decs); r.is_error()) {
323 return r.error();
324 }
325 written += decs.size();
326
327 auto toWrite = opts.minDecPlaces - decs.
size();
328 if (
auto r =
writer.write_n_times(
'0', toWrite); r.is_error()) {
329 return r.error();
330 }
331 written += toWrite;
332 }
333 else {
334 auto decsToWrite = decs.sub(0, opts.maxDecPlaces);
335 if (
auto r =
writer.write_all(decsToWrite); r.is_error()) {
336 return r.error();
337 }
338 written += decsToWrite.size();
339 }
340 auto finish = raw.sub(end);
341 if (!finish.empty()) {
342 if (
auto r =
writer.write_all(finish); r.is_error()) {
343 return r.error();
344 }
345 written += finish.size();
346 }
347
349 }
350 }
351 }
Result< Out, AsciiNumericParseError > base10_to_int(const Slice< const char > &parse)
Tries to parse an ASCII numeric string into an integer Will return an error if the parsed string does...
bool is_pos_int_str(Slice< const char > str)
Checks if a string is composed of only positive integer characters Will return false if string is emp...
constexpr Slice< char32_t > mut_slice_from(char32_t *cstr, size_t len)
Creates a mutable slice from a utf32 string and length.
bool starts_with(const Slice< T > &needle, const Slice< T > &haystack)
Checks whether a slice (the haystack) starts with elements in another slice in the same order (the ne...
constexpr Slice< const char32_t > slice_from(char32_t *cstr)
Creates a slice from a utf32 string in the form of a c string.
mtcore::Optional< size_t > first_index(const Slice< T > &needle, const Slice< T > &haystack)
Gets the first index that a needle appears in the haystack, or nullopt if the needle does not appear ...
bool contains(const std::remove_const_t< T > &needle, const Slice< T > &haystack)
Checks whether a slice (the haystack) contains an element (the needle) Uses the equality operator of ...
io::Writer< csv::impl::Writer< WI > > writer(io::Writer< WI > &underlying, Options opts={})
Creates a CSV writer which will encode the data before writing it out.
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Success< void > success()
Creates a successful void Result object.
Error< Underlying > error(Underlying err)
Creates an error.
int32_t i32
Alias for 32-bit ints.
auto to_chars(Slice< char > buff, double val, DragonboxFormatOptions={}) -> Result< Slice< char >, SliceWriteError >
auto round_compute_pow10_double(size_t d) -> double
constexpr Slice sub(size_t start) const noexcept
Gets a sub Slice from start.
constexpr size_t size() const noexcept
Gets the size of a Slice.
typename Impl::ErrType ErrType