]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/src/c++11/snprintf_lite.cc
1 // Debugging support -*- C++ -*-
3 // Copyright (C) 2013-2023 Free Software Foundation, Inc.
5 // This file is part of GCC.
7 // GCC is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3, or (at your option)
12 // GCC is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
28 #include <bits/functexcept.h>
32 // Private helper to throw logic error if snprintf_lite runs out
33 // of space (which is not expected to ever happen).
34 // NUL-terminates __buf.
36 __throw_insufficient_space(const char *__buf
, const char *__bufend
)
37 __attribute__((__noreturn__
));
40 __throw_insufficient_space(const char *__buf
, const char *__bufend
)
42 // Include space for trailing NUL.
43 const size_t __len
= __bufend
- __buf
+ 1;
45 const char __err
[] = "not enough space for format expansion "
46 "(Please submit full bug report at https://gcc.gnu.org/bugs/):\n ";
47 const size_t __errlen
= sizeof(__err
) - 1;
50 = static_cast<char*>(__builtin_alloca(__errlen
+ __len
));
52 __builtin_memcpy(__e
, __err
, __errlen
);
53 __builtin_memcpy(__e
+ __errlen
, __buf
, __len
- 1);
54 __e
[__errlen
+ __len
- 1] = '\0';
55 std::__throw_logic_error(__e
);
59 // Private routine to append decimal representation of VAL to the given
60 // BUFFER, but not more than BUFSIZE characters.
61 // Does not NUL-terminate the output buffer.
62 // Returns number of characters appended, or -1 if BUFSIZE is too small.
63 int __concat_size_t(char *__buf
, size_t __bufsize
, size_t __val
)
65 // Long enough for decimal representation.
66 int __ilen
= 3 * sizeof(__val
);
67 char *__cs
= static_cast<char*>(__builtin_alloca(__ilen
));
68 char* __out
= __cs
+ __ilen
;
71 *--__out
= "0123456789"[__val
% 10];
75 size_t __len
= __cs
+ __ilen
- __out
;
76 if (__bufsize
< __len
)
79 __builtin_memcpy(__buf
, __cs
+ __ilen
- __len
, __len
);
84 // Private routine to print into __buf arguments according to format,
85 // not to exceed __bufsize.
86 // Only '%%', '%s' and '%zu' format specifiers are understood.
87 // Returns number of characters printed (excluding terminating NUL).
88 // Always NUL-terminates __buf.
89 // Throws logic_error on insufficient space.
90 int __snprintf_lite(char *__buf
, size_t __bufsize
, const char *__fmt
,
94 const char *__s
= __fmt
;
95 const char *const __limit
= __d
+ __bufsize
- 1; // Leave space for NUL.
97 while (__s
[0] != '\0' && __d
< __limit
)
102 default: // Stray '%'. Just print it.
109 const char *__v
= va_arg(__ap
, const char *);
111 while (__v
[0] != '\0' && __d
< __limit
)
115 // Not enough space for __fmt expansion.
116 __throw_insufficient_space(__buf
, __d
);
118 __s
+= 2; // Step over %s.
123 if (__s
[2] == 'u') // '%zu' -- expand next size_t arg.
125 const int __len
= __concat_size_t(__d
, __limit
- __d
,
126 va_arg(__ap
, size_t));
130 // Not enough space for __fmt expansion.
131 __throw_insufficient_space(__buf
, __d
);
133 __s
+= 3; // Step over %zu
136 // Stray '%zX'. Just print it.
143 // Not enough space for __fmt expansion.
144 __throw_insufficient_space(__buf
, __d
);