Coverage Report

Created: 2026-02-10 07:39

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
};
72
73
enum GooStringFormatType
74
{
75
    fmtIntDecimal,
76
    fmtIntHex,
77
    fmtIntHexUpper,
78
    fmtIntOctal,
79
    fmtIntBinary,
80
    fmtUIntDecimal,
81
    fmtUIntHex,
82
    fmtUIntHexUpper,
83
    fmtUIntOctal,
84
    fmtUIntBinary,
85
    fmtLongDecimal,
86
    fmtLongHex,
87
    fmtLongHexUpper,
88
    fmtLongOctal,
89
    fmtLongBinary,
90
    fmtULongDecimal,
91
    fmtULongHex,
92
    fmtULongHexUpper,
93
    fmtULongOctal,
94
    fmtULongBinary,
95
    fmtLongLongDecimal,
96
    fmtLongLongHex,
97
    fmtLongLongHexUpper,
98
    fmtLongLongOctal,
99
    fmtLongLongBinary,
100
    fmtULongLongDecimal,
101
    fmtULongLongHex,
102
    fmtULongLongHexUpper,
103
    fmtULongLongOctal,
104
    fmtULongLongBinary,
105
    fmtDouble,
106
    fmtDoubleTrimSmallAware,
107
    fmtDoubleTrim,
108
    fmtChar,
109
    fmtString,
110
    fmtGooString,
111
    fmtSpace,
112
    fmtInvalidFormat
113
};
114
115
const char *const formatStrings[] = { "d",   "x",   "X",   "o",   "b",   "ud",  "ux",   "uX",   "uo",   "ub",   "ld",   "lx", "lX", "lo", "lb", "uld", "ulx", "ulX", "ulo",
116
                                      "ulb", "lld", "llx", "llX", "llo", "llb", "ulld", "ullx", "ullX", "ullo", "ullb", "f",  "gs", "g",  "c",  "s",   "t",   "w",   nullptr };
117
static_assert((fmtInvalidFormat + 1) == (sizeof(formatStrings) / sizeof(char *)));
118
119
void formatInt(long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase = false);
120
121
void formatUInt(unsigned long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase = false);
122
123
void formatDouble(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len);
124
125
void formatDoubleSmallAware(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len);
126
127
}
128
129
//------------------------------------------------------------------------
130
131
std::string GooString::format(const char *fmt, ...)
132
2.17G
{
133
2.17G
    GooString s;
134
135
2.17G
    va_list argList;
136
2.17G
    va_start(argList, fmt);
137
2.17G
    s.appendfv(fmt, argList);
138
2.17G
    va_end(argList);
139
140
2.17G
    return s.toStr();
141
2.17G
}
142
143
std::string GooString::formatv(const char *fmt, va_list argList)
144
482M
{
145
482M
    GooString s;
146
147
482M
    s.appendfv(fmt, argList);
148
149
482M
    return s.toStr();
150
482M
}
151
152
GooString *GooString::appendf(const char *fmt, ...)
153
29.3M
{
154
29.3M
    va_list argList;
155
29.3M
    va_start(argList, fmt);
156
29.3M
    appendfv(fmt, argList);
157
29.3M
    va_end(argList);
158
159
29.3M
    return this;
160
29.3M
}
161
162
GooString *GooString::appendfv(const char *fmt, va_list argList)
163
2.69G
{
164
2.69G
    GooStringFormatArg *args;
165
2.69G
    int argsLen, argsSize;
166
2.69G
    GooStringFormatArg arg;
167
2.69G
    int idx, width, prec;
168
2.69G
    bool reverseAlign, zeroFill;
169
2.69G
    GooStringFormatType ft;
170
2.69G
    char buf[65];
171
2.69G
    int len, i;
172
2.69G
    const char *p0, *p1;
173
2.69G
    const char *str;
174
2.69G
    GooStringFormatArg argsBuf[8];
175
176
2.69G
    argsLen = 0;
177
2.69G
    argsSize = sizeof(argsBuf) / sizeof(argsBuf[0]);
178
2.69G
    args = argsBuf;
179
180
2.69G
    p0 = fmt;
181
6.28G
    while (*p0) {
182
3.58G
        if (*p0 == '{') {
183
2.58G
            ++p0;
184
2.58G
            if (*p0 == '{') {
185
46.3k
                ++p0;
186
46.3k
                push_back('{');
187
2.58G
            } else {
188
189
                // parse the format string
190
2.58G
                if (*p0 < '0' || *p0 > '9') {
191
0
                    break;
192
0
                }
193
2.58G
                idx = *p0 - '0';
194
2.58G
                for (++p0; *p0 >= '0' && *p0 <= '9'; ++p0) {
195
0
                    idx = 10 * idx + (*p0 - '0');
196
0
                }
197
2.58G
                if (*p0 != ':') {
198
0
                    break;
199
0
                }
200
2.58G
                ++p0;
201
2.58G
                if (*p0 == '-') {
202
0
                    reverseAlign = true;
203
0
                    ++p0;
204
2.58G
                } else {
205
2.58G
                    reverseAlign = false;
206
2.58G
                }
207
2.58G
                width = 0;
208
2.58G
                zeroFill = *p0 == '0';
209
7.51G
                for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
210
4.92G
                    width = 10 * width + (*p0 - '0');
211
4.92G
                }
212
2.58G
                if (width < 0) {
213
0
                    width = 0;
214
0
                }
215
2.58G
                if (*p0 == '.') {
216
30.1M
                    ++p0;
217
30.1M
                    prec = 0;
218
60.3M
                    for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
219
30.1M
                        prec = 10 * prec + (*p0 - '0');
220
30.1M
                    }
221
2.55G
                } else {
222
2.55G
                    prec = 0;
223
2.55G
                }
224
6.83G
                for (ft = (GooStringFormatType)0; formatStrings[ft]; ft = (GooStringFormatType)(ft + 1)) {
225
6.83G
                    if (!strncmp(p0, formatStrings[ft], strlen(formatStrings[ft]))) {
226
2.58G
                        break;
227
2.58G
                    }
228
6.83G
                }
229
2.58G
                if (!formatStrings[ft]) {
230
0
                    break;
231
0
                }
232
2.58G
                p0 += strlen(formatStrings[ft]);
233
2.58G
                if (*p0 != '}') {
234
0
                    break;
235
0
                }
236
2.58G
                ++p0;
237
238
                // fetch the argument
239
2.58G
                if (idx > argsLen) {
240
0
                    break;
241
0
                }
242
2.58G
                if (idx == argsLen) {
243
2.58G
                    if (argsLen == argsSize) {
244
4.68k
                        argsSize *= 2;
245
4.68k
                        if (args == argsBuf) {
246
4.68k
                            args = (GooStringFormatArg *)gmallocn(argsSize, sizeof(GooStringFormatArg));
247
4.68k
                            memcpy(args, argsBuf, argsLen * sizeof(GooStringFormatArg));
248
4.68k
                        } else {
249
0
                            args = (GooStringFormatArg *)greallocn(args, argsSize, sizeof(GooStringFormatArg));
250
0
                        }
251
4.68k
                    }
252
2.58G
                    switch (ft) {
253
67.2M
                    case fmtIntDecimal:
254
2.52G
                    case fmtIntHex:
255
2.52G
                    case fmtIntHexUpper:
256
2.52G
                    case fmtIntOctal:
257
2.52G
                    case fmtIntBinary:
258
2.52G
                    case fmtSpace:
259
2.52G
                        args[argsLen].i = va_arg(argList, int);
260
2.52G
                        break;
261
154k
                    case fmtUIntDecimal:
262
157k
                    case fmtUIntHex:
263
280k
                    case fmtUIntHexUpper:
264
280k
                    case fmtUIntOctal:
265
280k
                    case fmtUIntBinary:
266
280k
                        args[argsLen].ui = va_arg(argList, unsigned int);
267
280k
                        break;
268
0
                    case fmtLongDecimal:
269
0
                    case fmtLongHex:
270
0
                    case fmtLongHexUpper:
271
0
                    case fmtLongOctal:
272
0
                    case fmtLongBinary:
273
0
                        args[argsLen].l = va_arg(argList, long);
274
0
                        break;
275
1.01M
                    case fmtULongDecimal:
276
1.01M
                    case fmtULongHex:
277
1.01M
                    case fmtULongHexUpper:
278
1.01M
                    case fmtULongOctal:
279
1.01M
                    case fmtULongBinary:
280
1.01M
                        args[argsLen].ul = va_arg(argList, unsigned long);
281
1.01M
                        break;
282
0
                    case fmtLongLongDecimal:
283
0
                    case fmtLongLongHex:
284
0
                    case fmtLongLongHexUpper:
285
0
                    case fmtLongLongOctal:
286
0
                    case fmtLongLongBinary:
287
0
                        args[argsLen].ll = va_arg(argList, long long);
288
0
                        break;
289
0
                    case fmtULongLongDecimal:
290
0
                    case fmtULongLongHex:
291
0
                    case fmtULongLongHexUpper:
292
0
                    case fmtULongLongOctal:
293
0
                    case fmtULongLongBinary:
294
0
                        args[argsLen].ull = va_arg(argList, unsigned long long);
295
0
                        break;
296
6.24M
                    case fmtDouble:
297
29.4M
                    case fmtDoubleTrim:
298
30.2M
                    case fmtDoubleTrimSmallAware:
299
30.2M
                        args[argsLen].f = va_arg(argList, double);
300
30.2M
                        break;
301
5.56M
                    case fmtChar:
302
5.56M
                        args[argsLen].c = (char)va_arg(argList, int);
303
5.56M
                        break;
304
18.4M
                    case fmtString:
305
18.4M
                        args[argsLen].s = va_arg(argList, char *);
306
18.4M
                        break;
307
77.0k
                    case fmtGooString:
308
77.0k
                        args[argsLen].gs = va_arg(argList, GooString *);
309
77.0k
                        break;
310
0
                    case fmtInvalidFormat:
311
0
                        assert(false);
312
2.58G
                    }
313
2.58G
                    ++argsLen;
314
2.58G
                }
315
316
                // format the argument
317
2.58G
                arg = args[idx];
318
2.58G
                switch (ft) {
319
67.2M
                case fmtIntDecimal:
320
67.2M
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
321
67.2M
                    break;
322
2.46G
                case fmtIntHex:
323
2.46G
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
324
2.46G
                    break;
325
0
                case fmtIntHexUpper:
326
0
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
327
0
                    break;
328
716k
                case fmtIntOctal:
329
716k
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
330
716k
                    break;
331
0
                case fmtIntBinary:
332
0
                    formatInt(arg.i, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
333
0
                    break;
334
154k
                case fmtUIntDecimal:
335
154k
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
336
154k
                    break;
337
3.19k
                case fmtUIntHex:
338
3.19k
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
339
3.19k
                    break;
340
122k
                case fmtUIntHexUpper:
341
122k
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
342
122k
                    break;
343
0
                case fmtUIntOctal:
344
0
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
345
0
                    break;
346
0
                case fmtUIntBinary:
347
0
                    formatUInt(arg.ui, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
348
0
                    break;
349
0
                case fmtLongDecimal:
350
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
351
0
                    break;
352
0
                case fmtLongHex:
353
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
354
0
                    break;
355
0
                case fmtLongHexUpper:
356
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
357
0
                    break;
358
0
                case fmtLongOctal:
359
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
360
0
                    break;
361
0
                case fmtLongBinary:
362
0
                    formatInt(arg.l, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
363
0
                    break;
364
1.01M
                case fmtULongDecimal:
365
1.01M
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
366
1.01M
                    break;
367
0
                case fmtULongHex:
368
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
369
0
                    break;
370
0
                case fmtULongHexUpper:
371
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
372
0
                    break;
373
0
                case fmtULongOctal:
374
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
375
0
                    break;
376
0
                case fmtULongBinary:
377
0
                    formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
378
0
                    break;
379
0
                case fmtLongLongDecimal:
380
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
381
0
                    break;
382
0
                case fmtLongLongHex:
383
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
384
0
                    break;
385
0
                case fmtLongLongHexUpper:
386
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
387
0
                    break;
388
0
                case fmtLongLongOctal:
389
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
390
0
                    break;
391
0
                case fmtLongLongBinary:
392
0
                    formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
393
0
                    break;
394
0
                case fmtULongLongDecimal:
395
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
396
0
                    break;
397
0
                case fmtULongLongHex:
398
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
399
0
                    break;
400
0
                case fmtULongLongHexUpper:
401
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16, &str, &len, true);
402
0
                    break;
403
0
                case fmtULongLongOctal:
404
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
405
0
                    break;
406
0
                case fmtULongLongBinary:
407
0
                    formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
408
0
                    break;
409
6.25M
                case fmtDouble:
410
6.25M
                    formatDouble(arg.f, buf, sizeof(buf), prec, false, &str, &len);
411
6.25M
                    break;
412
23.1M
                case fmtDoubleTrim:
413
23.1M
                    formatDouble(arg.f, buf, sizeof(buf), prec, true, &str, &len);
414
23.1M
                    break;
415
778k
                case fmtDoubleTrimSmallAware:
416
778k
                    formatDoubleSmallAware(arg.f, buf, sizeof(buf), prec, true, &str, &len);
417
778k
                    break;
418
5.56M
                case fmtChar:
419
5.56M
                    buf[0] = arg.c;
420
5.56M
                    str = buf;
421
5.56M
                    len = 1;
422
5.56M
                    reverseAlign = !reverseAlign;
423
5.56M
                    break;
424
18.4M
                case fmtString: {
425
18.4M
                    str = arg.s;
426
18.4M
                    const size_t strlen_str = strlen(str);
427
18.4M
                    if (strlen_str > static_cast<size_t>(std::numeric_limits<int>::max())) {
428
0
                        error(errSyntaxWarning, 0, "String truncated to INT_MAX bytes");
429
0
                        len = std::numeric_limits<int>::max();
430
18.4M
                    } else {
431
18.4M
                        len = static_cast<int>(strlen_str);
432
18.4M
                    }
433
18.4M
                    reverseAlign = !reverseAlign;
434
18.4M
                    break;
435
0
                }
436
77.0k
                case fmtGooString:
437
77.0k
                    if (arg.gs) {
438
77.0k
                        str = arg.gs->c_str();
439
77.0k
                        len = arg.gs->size();
440
77.0k
                    } else {
441
0
                        str = "(null)";
442
0
                        len = 6;
443
0
                    }
444
77.0k
                    reverseAlign = !reverseAlign;
445
77.0k
                    break;
446
4.32k
                case fmtSpace:
447
4.32k
                    str = buf;
448
4.32k
                    len = 0;
449
4.32k
                    width = arg.i;
450
4.32k
                    break;
451
0
                case fmtInvalidFormat:
452
0
                    assert(false);
453
2.58G
                }
454
455
                // append the formatted arg, handling width and alignment
456
2.58G
                if (!reverseAlign && len < width) {
457
14.1k
                    for (i = len; i < width; ++i) {
458
7.09k
                        push_back(' ');
459
7.09k
                    }
460
7.09k
                }
461
2.58G
                append(str, len);
462
2.58G
                if (reverseAlign && len < width) {
463
0
                    for (i = len; i < width; ++i) {
464
0
                        push_back(' ');
465
0
                    }
466
0
                }
467
2.58G
            }
468
469
2.58G
        } else if (*p0 == '}') {
470
42.5k
            ++p0;
471
42.5k
            if (*p0 == '}') {
472
42.5k
                ++p0;
473
42.5k
            }
474
42.5k
            push_back('}');
475
476
1.00G
        } else {
477
16.2G
            for (p1 = p0 + 1; *p1 && *p1 != '{' && *p1 != '}'; ++p1) {
478
15.2G
                ;
479
15.2G
            }
480
1.00G
            append(p0, p1 - p0);
481
1.00G
            p0 = p1;
482
1.00G
        }
483
3.58G
    }
484
485
2.69G
    if (args != argsBuf) {
486
4.68k
        gfree(args);
487
4.68k
    }
488
489
2.69G
    return this;
490
2.69G
}
491
492
namespace {
493
494
const char lowerCaseDigits[17] = "0123456789abcdef";
495
const char upperCaseDigits[17] = "0123456789ABCDEF";
496
497
void formatInt(long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase)
498
2.52G
{
499
2.52G
    const char *vals = upperCase ? upperCaseDigits : lowerCaseDigits;
500
2.52G
    bool neg;
501
2.52G
    int start, i, j;
502
2.52G
    unsigned long long abs_x;
503
504
2.52G
    i = bufSize;
505
2.52G
    if ((neg = x < 0)) {
506
266k
        abs_x = -x;
507
2.52G
    } else {
508
2.52G
        abs_x = x;
509
2.52G
    }
510
2.52G
    start = neg ? 1 : 0;
511
2.52G
    if (abs_x == 0) {
512
241M
        buf[--i] = '0';
513
2.28G
    } else {
514
6.47G
        while (i > start && abs_x) {
515
4.18G
            buf[--i] = vals[abs_x % base];
516
4.18G
            abs_x /= base;
517
4.18G
        }
518
2.28G
    }
519
2.52G
    if (zeroFill) {
520
3.12G
        for (j = bufSize - i; i > start && j < width - start; ++j) {
521
657M
            buf[--i] = '0';
522
657M
        }
523
2.46G
    }
524
2.52G
    if (neg) {
525
266k
        buf[--i] = '-';
526
266k
    }
527
2.52G
    *p = buf + i;
528
2.52G
    *len = bufSize - i;
529
2.52G
}
530
531
void formatUInt(unsigned long long x, char *buf, int bufSize, bool zeroFill, int width, int base, const char **p, int *len, bool upperCase)
532
1.29M
{
533
1.29M
    const char *vals = upperCase ? upperCaseDigits : lowerCaseDigits;
534
1.29M
    int i, j;
535
536
1.29M
    i = bufSize;
537
1.29M
    if (x == 0) {
538
2.95k
        buf[--i] = '0';
539
1.29M
    } else {
540
3.95M
        while (i > 0 && x) {
541
2.66M
            buf[--i] = vals[x % base];
542
2.66M
            x /= base;
543
2.66M
        }
544
1.29M
    }
545
1.29M
    if (zeroFill) {
546
349k
        for (j = bufSize - i; i > 0 && j < width; ++j) {
547
226k
            buf[--i] = '0';
548
226k
        }
549
122k
    }
550
1.29M
    *p = buf + i;
551
1.29M
    *len = bufSize - i;
552
1.29M
}
553
554
void formatDouble(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len)
555
30.2M
{
556
30.2M
    bool neg, started;
557
30.2M
    double x2;
558
30.2M
    int d, i, j;
559
560
30.2M
    if ((neg = x < 0)) {
561
4.43M
        x = -x;
562
4.43M
    }
563
30.2M
    x = floor(x * pow(10.0, prec) + 0.5);
564
30.2M
    i = bufSize;
565
30.2M
    started = !trim;
566
186M
    for (j = 0; j < prec && i > 1; ++j) {
567
155M
        x2 = floor(0.1 * (x + 0.5));
568
155M
        d = (int)floor(x - 10 * x2 + 0.5);
569
155M
        if (started || d != 0) {
570
85.2M
            buf[--i] = '0' + d;
571
85.2M
            started = true;
572
85.2M
        }
573
155M
        x = x2;
574
155M
    }
575
30.2M
    if (i > 1 && started) {
576
21.0M
        buf[--i] = '.';
577
21.0M
    }
578
30.2M
    if (i > 1) {
579
61.4M
        do {
580
61.4M
            x2 = floor(0.1 * (x + 0.5));
581
61.4M
            d = (int)floor(x - 10 * x2 + 0.5);
582
61.4M
            buf[--i] = '0' + d;
583
61.4M
            x = x2;
584
61.4M
        } while (i > 1 && x);
585
30.2M
    }
586
30.2M
    if (neg) {
587
4.43M
        buf[--i] = '-';
588
4.43M
    }
589
30.2M
    *p = buf + i;
590
30.2M
    *len = bufSize - i;
591
30.2M
}
592
593
void formatDoubleSmallAware(double x, char *buf, int bufSize, int prec, bool trim, const char **p, int *len)
594
778k
{
595
778k
    double absX = fabs(x);
596
778k
    if (absX >= 0.1) {
597
455k
        formatDouble(x, buf, bufSize, prec, trim, p, len);
598
455k
    } else {
599
3.48M
        while (absX < 0.1 && prec < 16) {
600
3.16M
            absX = absX * 10;
601
3.16M
            prec++;
602
3.16M
        }
603
322k
        formatDouble(x, buf, bufSize, prec, trim, p, len);
604
322k
    }
605
778k
}
606
607
}
608
609
void GooString::lowerCase(std::string &s)
610
90
{
611
155
    for (auto &c : s) {
612
155
        if (std::isupper(c)) {
613
75
            c = std::tolower(c);
614
75
        }
615
155
    }
616
90
}
617
618
std::string GooString::toLowerCase(std::string_view s)
619
90
{
620
90
    std::string newString(s);
621
90
    lowerCase(newString);
622
90
    return newString;
623
90
}