Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/goo/GooString.cc
Line
Count
Source
1
//========================================================================
2
//
3
// GooString.cc
4
//
5
// Simple variable-length string type.
6
//
7
// Copyright 1996-2003 Glyph & Cog, LLC
8
//
9
//========================================================================
10
11
//========================================================================
12
//
13
// Modified under the Poppler project - http://poppler.freedesktop.org
14
//
15
// All changes made under the Poppler project to this file are licensed
16
// under GPL version 2 or later
17
//
18
// Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
19
// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
20
// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
21
// Copyright (C) 2008-2011, 2016-2018, 2022, 2025 Albert Astals Cid <aacid@kde.org>
22
// Copyright (C) 2011 Kenji Uno <ku@digitaldolphins.jp>
23
// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
24
// Copyright (C) 2012, 2017 Adrian Johnson <ajohnson@redneon.com>
25
// Copyright (C) 2012 Pino Toscano <pino@kde.org>
26
// Copyright (C) 2013 Jason Crain <jason@aquaticape.us>
27
// Copyright (C) 2015 William Bader <williambader@hotmail.com>
28
// Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
29
// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
30
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
31
// Copyright (C) 2018 Greg Knight <lyngvi@gmail.com>
32
// Copyright (C) 2019, 2022-2024 Oliver Sander <oliver.sander@tu-dresden.de>
33
// Copyright (C) 2023 Even Rouault <even.rouault@mines-paris.org>
34
// Copyright (C) 2025, 2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
35
// Copyright (C) 2025 Jonathan Hähne <jonathan.haehne@hotmail.com>
36
//
37
// To see a description of the changes please see the Changelog file that
38
// came with your tarball or type make ChangeLog if you are building from git
39
//
40
//========================================================================
41
42
#include <config.h>
43
44
#include <cassert>
45
#include <cctype>
46
#include <cmath>
47
#include <cstddef>
48
#include <cstdlib>
49
#include <cstring>
50
#include <limits>
51
52
#include "gmem.h"
53
#include "Error.h"
54
#include "GooString.h"
55
56
//------------------------------------------------------------------------
57
58
namespace {
59
60
union GooStringFormatArg {
61
    int i;
62
    unsigned int ui;
63
    long l;
64
    unsigned long ul;
65
    long long ll;
66
    unsigned long long ull;
67
    double f;
68
    char c;
69
    char *s;
70
    GooString *gs;
71
    std::string *r;
72
};
73
74
enum GooStringFormatType
75
{
76
    fmtIntDecimal,
77
    fmtIntHex,
78
    fmtIntHexUpper,
79
    fmtIntOctal,
80
    fmtIntBinary,
81
    fmtUIntDecimal,
82
    fmtUIntHex,
83
    fmtUIntHexUpper,
84
    fmtUIntOctal,
85
    fmtUIntBinary,
86
    fmtLongDecimal,
87
    fmtLongHex,
88
    fmtLongHexUpper,
89
    fmtLongOctal,
90
    fmtLongBinary,
91
    fmtULongDecimal,
92
    fmtULongHex,
93
    fmtULongHexUpper,
94
    fmtULongOctal,
95
    fmtULongBinary,
96
    fmtLongLongDecimal,
97
    fmtLongLongHex,
98
    fmtLongLongHexUpper,
99
    fmtLongLongOctal,
100
    fmtLongLongBinary,
101
    fmtULongLongDecimal,
102
    fmtULongLongHex,
103
    fmtULongLongHexUpper,
104
    fmtULongLongOctal,
105
    fmtULongLongBinary,
106
    fmtDouble,
107
    fmtDoubleTrimSmallAware,
108
    fmtDoubleTrim,
109
    fmtChar,
110
    fmtString,
111
    fmtGooString,
112
    fmtStdString,
113
    fmtSpace,
114
    fmtInvalidFormat
115
};
116
117
const char *const formatStrings[] = { "d",   "x",   "X",   "o",   "b",   "ud",   "ux",   "uX",   "uo",   "ub",   "ld", "lx", "lX", "lo", "lb", "uld", "ulx", "ulX", "ulo",  "ulb",
118
                                      "lld", "llx", "llX", "llo", "llb", "ulld", "ullx", "ullX", "ullo", "ullb", "f",  "gs", "g",  "c",  "s",  "t",   "r",   "w",   nullptr };
119
static_assert((fmtInvalidFormat + 1) == (sizeof(formatStrings) / sizeof(char *)));
120
121
void formatInt(long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase = false);
122
123
void formatUInt(unsigned long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase = false);
124
125
void formatDouble(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len);
126
127
void formatDoubleSmallAware(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len);
128
129
}
130
131
//------------------------------------------------------------------------
132
133
std::string GooString::format(const char *fmt, ...)
134
632
{
135
632
    std::string s;
136
137
632
    va_list argList;
138
632
    va_start(argList, fmt);
139
632
    appendfv(s, fmt, argList);
140
632
    va_end(argList);
141
142
632
    return s;
143
632
}
144
145
std::string GooString::formatv(const char *fmt, va_list argList)
146
39.6M
{
147
39.6M
    std::string s;
148
149
39.6M
    appendfv(s, fmt, argList);
150
151
39.6M
    return s;
152
39.6M
}
153
154
std::string &GooString::appendf(std::string &that, const char *fmt, ...)
155
2.31M
{
156
2.31M
    va_list argList;
157
2.31M
    va_start(argList, fmt);
158
2.31M
    appendfv(that, fmt, argList);
159
2.31M
    va_end(argList);
160
161
2.31M
    return that;
162
2.31M
}
163
164
std::string &GooString::appendfv(std::string &that, const char *fmt, va_list argList)
165
42.0M
{
166
42.0M
    GooStringFormatArg *args;
167
42.0M
    int argsLen, argsSize;
168
42.0M
    GooStringFormatArg arg;
169
42.0M
    int idx, width, prec;
170
42.0M
    bool reverseAlign, zeroFill;
171
42.0M
    GooStringFormatType ft;
172
42.0M
    char buf[65];
173
42.0M
    int len, i;
174
42.0M
    const char *p0, *p1;
175
42.0M
    const char *str;
176
42.0M
    GooStringFormatArg argsBuf[8];
177
178
42.0M
    argsLen = 0;
179
42.0M
    argsSize = sizeof(argsBuf) / sizeof(argsBuf[0]);
180
42.0M
    args = argsBuf;
181
182
42.0M
    p0 = fmt;
183
148M
    while (*p0) {
184
106M
        if (*p0 == '{') {
185
32.3M
            ++p0;
186
32.3M
            if (*p0 == '{') {
187
9
                ++p0;
188
9
                that.push_back('{');
189
32.3M
            } else {
190
191
                // parse the format string
192
32.3M
                if (*p0 < '0' || *p0 > '9') {
193
0
                    break;
194
0
                }
195
32.3M
                idx = *p0 - '0';
196
32.3M
                for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
197
0
                    idx = 10 * idx + (*p0 - '0');
198
0
                }
199
32.3M
                if (*p0 != ':') {
200
0
                    break;
201
0
                }
202
32.3M
                ++p0;
203
32.3M
                if (*p0 == '-') {
204
0
                    reverseAlign = true;
205
0
                    ++p0;
206
32.3M
                } else {
207
32.3M
                    reverseAlign = false;
208
32.3M
                }
209
32.3M
                width = 0;
210
32.3M
                zeroFill = *p0 == '0';
211
90.8M
                for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
212
58.5M
                    width = 10 * width + (*p0 - '0');
213
58.5M
                }
214
32.3M
                if (width < 0) {
215
0
                    width = 0;
216
0
                }
217
32.3M
                if (*p0 == '.') {
218
125k
                    ++p0;
219
125k
                    prec = 0;
220
251k
                    for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
221
125k
                        prec = 10 * prec + (*p0 - '0');
222
125k
                    }
223
32.2M
                } else {
224
32.2M
                    prec = 0;
225
32.2M
                }
226
112M
                for (ft = static_cast<GooStringFormatType>(0); formatStrings[ft]; ft = static_cast<GooStringFormatType>(ft + 1)) {
227
112M
                    if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
228
32.3M
                        break;
229
32.3M
                    }
230
112M
                }
231
32.3M
                if (!formatStrings[ft]) {
232
0
                    break;
233
0
                }
234
32.3M
                p0 += strlen(formatStrings[ft]);
235
32.3M
                if (*p0 != '}') {
236
0
                    break;
237
0
                }
238
32.3M
                ++p0;
239
240
                // fetch the argument
241
32.3M
                if (idx > argsLen) {
242
0
                    break;
243
0
                }
244
32.3M
                if (idx == argsLen) {
245
32.3M
                    if (argsLen == argsSize) {
246
0
                        argsSize *= 2;
247
0
                        if (args == argsBuf) {
248
0
                            args = static_cast<GooStringFormatArg *>(gmallocn(argsSize, sizeof(GooStringFormatArg)));
249
0
                            memcpy(args, argsBuf, argsLen * sizeof(GooStringFormatArg));
250
0
                        } else {
251
0
                            args = static_cast<GooStringFormatArg *>(greallocn(args, argsSize, sizeof(GooStringFormatArg)));
252
0
                        }
253
0
                    }
254
32.3M
                    switch (ft) {
255
1.61M
                    case fmtIntDecimal:
256
30.8M
                    case fmtIntHex:
257
30.8M
                    case fmtIntHexUpper:
258
30.8M
                    case fmtIntOctal:
259
30.8M
                    case fmtIntBinary:
260
30.8M
                    case fmtSpace:
261
30.8M
                        args[argsLen].i = va_arg(argList, int);
262
30.8M
                        break;
263
758
                    case fmtUIntDecimal:
264
758
                    case fmtUIntHex:
265
1.35k
                    case fmtUIntHexUpper:
266
1.35k
                    case fmtUIntOctal:
267
1.35k
                    case fmtUIntBinary:
268
1.35k
                        args[argsLen].ui = va_arg(argList, unsigned int);
269
1.35k
                        break;
270
0
                    case fmtLongDecimal:
271
0
                    case fmtLongHex:
272
0
                    case fmtLongHexUpper:
273
0
                    case fmtLongOctal:
274
0
                    case fmtLongBinary:
275
0
                        args[argsLen].l = va_arg(argList, long);
276
0
                        break;
277
6.12k
                    case fmtULongDecimal:
278
6.12k
                    case fmtULongHex:
279
6.12k
                    case fmtULongHexUpper:
280
6.12k
                    case fmtULongOctal:
281
6.12k
                    case fmtULongBinary:
282
6.12k
                        args[argsLen].ul = va_arg(argList, unsigned long);
283
6.12k
                        break;
284
0
                    case fmtLongLongDecimal:
285
0
                    case fmtLongLongHex:
286
0
                    case fmtLongLongHexUpper:
287
0
                    case fmtLongLongOctal:
288
0
                    case fmtLongLongBinary:
289
0
                        args[argsLen].ll = va_arg(argList, long long);
290
0
                        break;
291
0
                    case fmtULongLongDecimal:
292
0
                    case fmtULongLongHex:
293
0
                    case fmtULongLongHexUpper:
294
0
                    case fmtULongLongOctal:
295
0
                    case fmtULongLongBinary:
296
0
                        args[argsLen].ull = va_arg(argList, unsigned long long);
297
0
                        break;
298
124k
                    case fmtDouble:
299
125k
                    case fmtDoubleTrim:
300
125k
                    case fmtDoubleTrimSmallAware:
301
125k
                        args[argsLen].f = va_arg(argList, double);
302
125k
                        break;
303
443k
                    case fmtChar:
304
443k
                        args[argsLen].c = static_cast<char>(va_arg(argList, int));
305
443k
                        break;
306
772k
                    case fmtString:
307
772k
                        args[argsLen].s = va_arg(argList, char *);
308
772k
                        break;
309
63
                    case fmtGooString:
310
63
                        args[argsLen].gs = va_arg(argList, GooString *);
311
63
                        break;
312
157k
                    case fmtStdString:
313
157k
                        args[argsLen].r = va_arg(argList, std::string *);
314
157k
                        break;
315
0
                    case fmtInvalidFormat:
316
0
                        assert(false);
317
32.3M
                    }
318
32.3M
                    ++argsLen;
319
32.3M
                }
320
321
                // format the argument
322
32.3M
                arg = args[idx];
323
32.3M
                switch (ft) {
324
1.61M
                case fmtIntDecimal:
325
1.61M
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
326
1.61M
                    break;
327
29.2M
                case fmtIntHex:
328
29.2M
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
329
29.2M
                    break;
330
0
                case fmtIntHexUpper:
331
0
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
332
0
                    break;
333
1.30k
                case fmtIntOctal:
334
1.30k
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
335
1.30k
                    break;
336
0
                case fmtIntBinary:
337
0
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
338
0
                    break;
339
758
                case fmtUIntDecimal:
340
758
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
341
758
                    break;
342
0
                case fmtUIntHex:
343
0
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
344
0
                    break;
345
601
                case fmtUIntHexUpper:
346
601
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
347
601
                    break;
348
0
                case fmtUIntOctal:
349
0
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
350
0
                    break;
351
0
                case fmtUIntBinary:
352
0
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
353
0
                    break;
354
0
                case fmtLongDecimal:
355
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
356
0
                    break;
357
0
                case fmtLongHex:
358
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
359
0
                    break;
360
0
                case fmtLongHexUpper:
361
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
362
0
                    break;
363
0
                case fmtLongOctal:
364
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
365
0
                    break;
366
0
                case fmtLongBinary:
367
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
368
0
                    break;
369
6.12k
                case fmtULongDecimal:
370
6.12k
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
371
6.12k
                    break;
372
0
                case fmtULongHex:
373
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
374
0
                    break;
375
0
                case fmtULongHexUpper:
376
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
377
0
                    break;
378
0
                case fmtULongOctal:
379
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
380
0
                    break;
381
0
                case fmtULongBinary:
382
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
383
0
                    break;
384
0
                case fmtLongLongDecimal:
385
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
386
0
                    break;
387
0
                case fmtLongLongHex:
388
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
389
0
                    break;
390
0
                case fmtLongLongHexUpper:
391
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
392
0
                    break;
393
0
                case fmtLongLongOctal:
394
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
395
0
                    break;
396
0
                case fmtLongLongBinary:
397
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
398
0
                    break;
399
0
                case fmtULongLongDecimal:
400
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
401
0
                    break;
402
0
                case fmtULongLongHex:
403
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
404
0
                    break;
405
0
                case fmtULongLongHexUpper:
406
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
407
0
                    break;
408
0
                case fmtULongLongOctal:
409
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
410
0
                    break;
411
0
                case fmtULongLongBinary:
412
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
413
0
                    break;
414
125k
                case fmtDouble:
415
125k
                    formatDouble(arg.f, buf, sizeof(buf), prec, false, &str, &len);
416
125k
                    break;
417
444
                case fmtDoubleTrim:
418
444
                    formatDouble(arg.f, buf, sizeof(buf), prec, true, &str, &len);
419
444
                    break;
420
0
                case fmtDoubleTrimSmallAware:
421
0
                    formatDoubleSmallAware(arg.f, buf, sizeof(buf), prec, true, &str, &len);
422
0
                    break;
423
443k
                case fmtChar:
424
443k
                    buf[0] = arg.c;
425
443k
                    str = buf;
426
443k
                    len = 1;
427
443k
                    reverseAlign = !reverseAlign;
428
443k
                    break;
429
772k
                case fmtString: {
430
772k
                    str = arg.s;
431
772k
                    const size_t strlen_str = strlen(str);
432
772k
                    if (strlen_str > static_cast<size_t>(std::numeric_limits<int>::max())) {
433
0
                        error(errSyntaxWarning, 0, "String truncated to INT_MAX bytes");
434
0
                        len = std::numeric_limits<int>::max();
435
772k
                    } else {
436
772k
                        len = static_cast<int>(strlen_str);
437
772k
                    }
438
772k
                    reverseAlign = !reverseAlign;
439
772k
                    break;
440
0
                }
441
63
                case fmtGooString:
442
63
                    if (arg.gs) {
443
63
                        str = arg.gs->c_str();
444
63
                        len = arg.gs->size();
445
63
                    } else {
446
0
                        str = "(null)";
447
0
                        len = 6;
448
0
                    }
449
63
                    reverseAlign = !reverseAlign;
450
63
                    break;
451
157k
                case fmtStdString:
452
157k
                    if (arg.r) {
453
157k
                        str = arg.r->c_str();
454
157k
                        len = arg.r->size();
455
157k
                    } else {
456
0
                        str = "(null)";
457
0
                        len = 6;
458
0
                    }
459
157k
                    reverseAlign = !reverseAlign;
460
157k
                    break;
461
0
                case fmtSpace:
462
0
                    str = buf;
463
0
                    len = 0;
464
0
                    width = arg.i;
465
0
                    break;
466
0
                case fmtInvalidFormat:
467
0
                    assert(false);
468
32.3M
                }
469
470
                // append the formatted arg, handling width and alignment
471
32.3M
                if (!reverseAlign && len < width) {
472
0
                    for (i = len; i < width; ++i) {
473
0
                        that.push_back(' ');
474
0
                    }
475
0
                }
476
32.3M
                that.append(str, len);
477
32.3M
                if (reverseAlign && len < width) {
478
0
                    for (i = len; i < width; ++i) {
479
0
                        that.push_back(' ');
480
0
                    }
481
0
                }
482
32.3M
            }
483
484
74.3M
        } else if (*p0 == '}') {
485
0
            ++p0;
486
0
            if (*p0 == '}') {
487
0
                ++p0;
488
0
            }
489
0
            that.push_back('}');
490
491
74.3M
        } else {
492
1.32G
            for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) {
493
1.25G
                ;
494
1.25G
            }
495
74.3M
            that.append(p0, p1 - p0);
496
74.3M
            p0 = p1;
497
74.3M
        }
498
106M
    }
499
500
42.0M
    if (args != argsBuf) {
501
0
        gfree(args);
502
0
    }
503
504
42.0M
    return that;
505
42.0M
}
506
507
namespace {
508
509
const char lowerCaseDigits[17] = "0123456789abcdef";
510
const char upperCaseDigits[17] = "0123456789ABCDEF";
511
512
void formatInt(long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase)
513
30.8M
{
514
30.8M
    const char *vals = upperCase ? upperCaseDigits : lowerCaseDigits;
515
30.8M
    bool neg;
516
30.8M
    int start, i, j;
517
30.8M
    unsigned long long abs_x;
518
519
30.8M
    i = bufSize;
520
30.8M
    if ((neg = x < 0)) {
521
695
        abs_x = -x;
522
30.8M
    } else {
523
30.8M
        abs_x = x;
524
30.8M
    }
525
30.8M
    start = neg ? 1 : 0;
526
30.8M
    if (abs_x == 0) {
527
266k
        buf[--i] = '0';
528
30.6M
    } else {
529
92.2M
        while (i > start && abs_x) {
530
61.6M
            buf[--i] = vals[abs_x % base];
531
61.6M
            abs_x /= base;
532
61.6M
        }
533
30.6M
    }
534
30.8M
    if (zeroFill) {
535
30.5M
        for (j = bufSize - i; i > start && j < width - start; ++j) {
536
1.25M
            buf[--i] = '0';
537
1.25M
        }
538
29.2M
    }
539
30.8M
    if (neg) {
540
695
        buf[--i] = '-';
541
695
    }
542
30.8M
    *p = buf + i;
543
30.8M
    *len = bufSize - i;
544
30.8M
}
545
546
void formatUInt(unsigned long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase)
547
7.48k
{
548
7.48k
    const char *vals = upperCase ? upperCaseDigits : lowerCaseDigits;
549
7.48k
    int i, j;
550
551
7.48k
    i = bufSize;
552
7.48k
    if (x == 0) {
553
5
        buf[--i] = '0';
554
7.47k
    } else {
555
20.4k
        while (i > 0 && x) {
556
12.9k
            buf[--i] = vals[x % base];
557
12.9k
            x /= base;
558
12.9k
        }
559
7.47k
    }
560
7.48k
    if (zeroFill) {
561
1.79k
        for (j = bufSize - i; i > 0 && j < width; ++j) {
562
1.19k
            buf[--i] = '0';
563
1.19k
        }
564
601
    }
565
7.48k
    *p = buf + i;
566
7.48k
    *len = bufSize - i;
567
7.48k
}
568
569
void formatDouble(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len)
570
125k
{
571
125k
    bool neg, started;
572
125k
    double x2;
573
125k
    int d, i, j;
574
575
125k
    if ((neg = x < 0)) {
576
1.59k
        x = -x;
577
1.59k
    }
578
125k
    x = floor(x * pow(10.0, prec) + 0.5);
579
125k
    i = bufSize;
580
125k
    started = !trim;
581
389k
    for (j = 0; j < prec && i > 1; ++j) {
582
264k
        x2 = floor(0.1 * (x + 0.5));
583
264k
        d = static_cast<int>(floor(x - 10 * x2 + 0.5));
584
264k
        if (started || d != 0) {
585
264k
            buf[--i] = '0' + d;
586
264k
            started = true;
587
264k
        }
588
264k
        x = x2;
589
264k
    }
590
125k
    if (i > 1 && started) {
591
125k
        buf[--i] = '.';
592
125k
    }
593
125k
    if (i > 1) {
594
214k
        do {
595
214k
            x2 = floor(0.1 * (x + 0.5));
596
214k
            d = static_cast<int>(floor(x - 10 * x2 + 0.5));
597
214k
            buf[--i] = '0' + d;
598
214k
            x = x2;
599
214k
        } while (i > 1 && x);
600
125k
    }
601
125k
    if (neg) {
602
1.59k
        buf[--i] = '-';
603
1.59k
    }
604
125k
    *p = buf + i;
605
125k
    *len = bufSize - i;
606
125k
}
607
608
void formatDoubleSmallAware(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len)
609
0
{
610
0
    double absX = fabs(x);
611
0
    if (absX >= 0.1) {
612
0
        formatDouble(x, buf, bufSize, prec, trim, p, len);
613
0
    } else {
614
0
        while (absX < 0.1 && prec < 16) {
615
0
            absX = absX * 10;
616
0
            prec++;
617
0
        }
618
0
        formatDouble(x, buf, bufSize, prec, trim, p, len);
619
0
    }
620
0
}
621
622
}
623
624
void GooString::lowerCase(std::string &s)
625
0
{
626
0
    for (auto &c : s) {
627
0
        if (std::isupper(c)) {
628
0
            c = std::tolower(c);
629
0
        }
630
0
    }
631
0
}
632
633
std::string GooString::toLowerCase(std::string_view s)
634
0
{
635
0
    std::string newString(s);
636
0
    lowerCase(newString);
637
0
    return newString;
638
0
}