Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 : : * Author: Thun Lu <thun.lu@zohomail.cn>
4 : : * Repo: https://github.com/thun-res/vlink
5 : : * _ __ __ _ __
6 : : * | | / / / / (_) ____ / /__
7 : : * | | / / / / / / / __ \ / //_/
8 : : * | |/ / / /___ / / / / / / / ,<
9 : : * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 : : *
11 : : * Licensed under the Apache License, Version 2.0 (the "License");
12 : : * you may not use this file except in compliance with the License.
13 : : * You may obtain a copy of the License at
14 : : *
15 : : * http://www.apache.org/licenses/LICENSE-2.0
16 : : *
17 : : * Unless required by applicable law or agreed to in writing, software
18 : : * distributed under the License is distributed on an "AS IS" BASIS,
19 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 : : * See the License for the specific language governing permissions and
21 : : * limitations under the License.
22 : : */
23 : :
24 : : #include "./base/format.h"
25 : :
26 : : #include <cstdint>
27 : : #include <cstring>
28 : :
29 : : #include "./base/helpers.h"
30 : :
31 : : namespace vlink {
32 : : namespace format {
33 : : namespace detail {
34 : :
35 : : // NOLINTBEGIN
36 : 9 : size_t format_pointer_to(char* buf, const void* ptr) noexcept {
37 : : static constexpr const char kHexDigits[] = "0123456789abcdef";
38 : : static_assert(sizeof(uintptr_t) <= 8, "pointer size > 64bit not supported");
39 : :
40 : 9 : buf[0] = '0';
41 : 9 : buf[1] = 'x';
42 : :
43 : : char hex[16];
44 : 9 : int i = 16;
45 : 9 : auto value = reinterpret_cast<uintptr_t>(ptr);
46 : :
47 : : do {
48 : 23 : hex[--i] = kHexDigits[value & 0xF];
49 : 23 : value >>= 4;
50 [ + + ]: 23 : } while (value != 0);
51 : :
52 : 9 : size_t n = static_cast<size_t>(16 - i);
53 : 9 : std::memcpy(buf + 2, hex + i, n);
54 : :
55 : 9 : return 2 + n;
56 : : }
57 : :
58 : 4 : size_t format_float_to(char* buf, size_t buflen, float value) noexcept {
59 : 4 : return Helpers::format_floating_to(buf, buflen, value);
60 : : }
61 : :
62 : 9 : size_t format_double_to(char* buf, size_t buflen, double value) noexcept {
63 : 9 : return Helpers::format_floating_to(buf, buflen, value);
64 : : }
65 : :
66 : 1 : size_t format_long_double_to(char* buf, size_t buflen, long double value) noexcept {
67 : 1 : return Helpers::format_floating_to(buf, buflen, value);
68 : : }
69 : :
70 : 51 : size_t format_double_spec_to(char* buf, size_t buflen, double value, char type, int precision, bool alt) noexcept {
71 : 51 : return Helpers::format_floating_spec_to(buf, buflen, value, type, precision, alt);
72 : : }
73 : :
74 : 5 : size_t format_long_double_spec_to(char* buf, size_t buflen, long double value, char type, int precision,
75 : : bool alt) noexcept {
76 : 5 : return Helpers::format_floating_spec_to(buf, buflen, value, type, precision, alt);
77 : : }
78 : :
79 : 21 : const char* parse_spec_ref(const char* p, const char* end, int& ref) noexcept {
80 : 21 : ++p;
81 : 21 : int index = kSpecRefAuto;
82 : :
83 [ + - + - : 21 : if (p != end && *p >= '0' && *p <= '9') {
+ + ]
84 : 3 : index = 0;
85 : :
86 [ + - + - : 6 : while (p != end && *p >= '0' && *p <= '9') {
+ + ]
87 [ + - ]: 3 : if (index < 100000000) {
88 : 3 : index = index * 10 + (*p - '0');
89 : : }
90 : :
91 : 3 : ++p;
92 : : }
93 : : }
94 : :
95 [ + - + + ]: 21 : if (p != end && *p == '}') {
96 : 19 : ref = index;
97 : 19 : ++p;
98 : : }
99 : :
100 : 21 : return p;
101 : : }
102 : :
103 : 224 : const char* parse_format_spec(const char* p, const char* end, FormatSpec& spec) noexcept {
104 [ + - + + : 224 : if (p != end && p + 1 != end && (p[1] == '<' || p[1] == '>' || p[1] == '^') && *p != '{' && *p != '}') {
+ + + + +
+ + - +
- ]
105 : 8 : spec.fill = *p;
106 [ + + + + ]: 8 : spec.align = p[1] == '<' ? Align::kLeft : (p[1] == '>' ? Align::kRight : Align::kCenter);
107 : 8 : p += 2;
108 [ + - + + : 216 : } else if (p != end && (*p == '<' || *p == '>' || *p == '^')) {
+ + + + ]
109 [ + + + + ]: 27 : spec.align = *p == '<' ? Align::kLeft : (*p == '>' ? Align::kRight : Align::kCenter);
110 : 27 : ++p;
111 : : }
112 : :
113 [ + - + + : 224 : if (p != end && (*p == '+' || *p == '-' || *p == ' ')) {
+ + + + ]
114 [ + + + + ]: 13 : spec.sign = *p == '+' ? Sign::kPlus : (*p == ' ' ? Sign::kSpace : Sign::kMinus);
115 : 13 : ++p;
116 : : }
117 : :
118 [ + - + + ]: 224 : if (p != end && *p == '#') {
119 : 27 : spec.alt = true;
120 : 27 : ++p;
121 : : }
122 : :
123 [ + - + + ]: 224 : if (p != end && *p == '0') {
124 : 25 : spec.zero = true;
125 : 25 : ++p;
126 : : }
127 : :
128 [ + - + + ]: 224 : if (p != end && *p == '{') {
129 : 17 : p = parse_spec_ref(p, end, spec.width_ref);
130 : : } else {
131 [ + + + + : 305 : while (p != end && *p >= '0' && *p <= '9') {
+ + ]
132 [ + - ]: 98 : if (spec.width < 100000000) {
133 : 98 : spec.width = spec.width * 10 + (*p - '0');
134 : : }
135 : :
136 : 98 : ++p;
137 : : }
138 : : }
139 : :
140 [ + + + + ]: 224 : if (p != end && *p == '.') {
141 : 44 : ++p;
142 : 44 : spec.precision = 0;
143 : :
144 [ + - + + ]: 44 : if (p != end && *p == '{') {
145 : 4 : p = parse_spec_ref(p, end, spec.precision_ref);
146 : : } else {
147 [ + - + - : 84 : while (p != end && *p >= '0' && *p <= '9') {
+ + ]
148 [ + - ]: 44 : if (spec.precision < 100000000) {
149 : 44 : spec.precision = spec.precision * 10 + (*p - '0');
150 : : }
151 : :
152 : 44 : ++p;
153 : : }
154 : : }
155 : : }
156 : :
157 [ + + ]: 224 : if (p != end) {
158 [ + + ]: 223 : switch (*p) {
159 : 128 : case 'b':
160 : : case 'B':
161 : : case 'c':
162 : : case 'd':
163 : : case 'o':
164 : : case 'x':
165 : : case 'X':
166 : : case 'a':
167 : : case 'A':
168 : : case 'e':
169 : : case 'E':
170 : : case 'f':
171 : : case 'F':
172 : : case 'g':
173 : : case 'G':
174 : : case 's':
175 : : case 'p':
176 : : case '?':
177 : 128 : spec.type = *p;
178 : 128 : ++p;
179 : 128 : break;
180 : 95 : default:
181 : 95 : break;
182 : : }
183 : : }
184 : :
185 : 224 : return p;
186 : : }
187 : :
188 : : // NOLINTEND
189 : :
190 : : } // namespace detail
191 : : } // namespace format
192 : : } // namespace vlink
|