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 <cstdio>
28 : : #include <cstring>
29 : : #include <string_view>
30 : :
31 : : namespace vlink {
32 : : namespace format {
33 : : namespace detail {
34 : :
35 : : template <typename UIntT>
36 : 47 : inline static int count_digits(UIntT n) noexcept {
37 : 47 : int count = 1;
38 : :
39 [ + + ]: 140 : while (n >= 10) {
40 : 93 : n /= 10;
41 : 93 : ++count;
42 : : }
43 : :
44 : 47 : return count;
45 : : }
46 : :
47 : : template <typename UIntT>
48 : 47 : inline static void write_int_digits(char* buf, UIntT value, int num_digits) noexcept {
49 : 47 : char* end = buf + num_digits;
50 : :
51 [ + + ]: 140 : while (value >= 10) {
52 : 93 : auto digit = static_cast<unsigned>(value % 10);
53 : 93 : *--end = static_cast<char>('0' + digit);
54 : 93 : value /= 10;
55 : : }
56 : :
57 : 47 : *--end = static_cast<char>('0' + value);
58 : 47 : }
59 : :
60 : : // StringWriter
61 : 70 : StringWriter::StringWriter(char* buf, size_t size) noexcept : begin_(buf), ptr_(buf), end_(buf + size) {}
62 : :
63 : 70 : char* StringWriter::out() const noexcept { return ptr_; }
64 : :
65 : 0 : size_t StringWriter::written() const noexcept { return static_cast<size_t>(ptr_ - begin_); }
66 : :
67 : 70 : size_t StringWriter::total_size() const noexcept { return total_size_; }
68 : :
69 : 134 : void StringWriter::write(char c) {
70 : 134 : ++total_size_;
71 : :
72 [ + + ]: 134 : if VLIKELY (ptr_ < end_) {
73 : 122 : *ptr_++ = c;
74 : : }
75 : 134 : }
76 : :
77 : 64 : void StringWriter::write(const char* s, size_t count) {
78 : 64 : total_size_ += count;
79 : :
80 : 64 : auto avail = static_cast<size_t>(end_ - ptr_);
81 [ + + ]: 64 : size_t n = (count <= avail) ? count : avail;
82 : :
83 [ + + ]: 64 : if VLIKELY (n > 0) {
84 : 61 : std::memcpy(ptr_, s, n);
85 : 61 : ptr_ += n;
86 : : }
87 : 64 : }
88 : :
89 : 4 : void StringWriter::write(std::string_view sv) { write(sv.data(), sv.size()); }
90 : :
91 : : // NOLINTBEGIN
92 : 40 : size_t format_uint_to(char* buf, unsigned value) noexcept {
93 : 40 : int num_digits = count_digits(value);
94 : 40 : write_int_digits(buf, value, num_digits);
95 : :
96 : 40 : return static_cast<size_t>(num_digits);
97 : : }
98 : :
99 : 33 : size_t format_int_to(char* buf, int value) noexcept {
100 [ + + ]: 33 : if (value < 0) {
101 : 4 : buf[0] = '-';
102 : 4 : unsigned u = static_cast<unsigned>(-(value + 1)) + 1;
103 : :
104 : 4 : return 1 + format_uint_to(buf + 1, u);
105 : : }
106 : :
107 : 29 : return format_uint_to(buf, static_cast<unsigned>(value));
108 : : }
109 : :
110 : 7 : size_t format_ulong_long_to(char* buf, unsigned long long value) noexcept {
111 : 7 : int num_digits = count_digits(value);
112 : 7 : write_int_digits(buf, value, num_digits);
113 : :
114 : 7 : return static_cast<size_t>(num_digits);
115 : : }
116 : :
117 : 4 : size_t format_long_long_to(char* buf, long long value) noexcept {
118 [ + + ]: 4 : if (value < 0) {
119 : 2 : buf[0] = '-';
120 : 2 : unsigned long long u = static_cast<unsigned long long>(-(value + 1)) + 1;
121 : :
122 : 2 : return 1 + format_ulong_long_to(buf + 1, u);
123 : : }
124 : :
125 : 2 : return format_ulong_long_to(buf, static_cast<unsigned long long>(value));
126 : : }
127 : :
128 : 2 : size_t format_pointer_to(char* buf, const void* ptr) noexcept {
129 : : static constexpr const char kHexDigits[] = "0123456789abcdef";
130 : : static_assert(sizeof(uintptr_t) <= 8, "pointer size > 64bit not supported");
131 : :
132 : 2 : buf[0] = '0';
133 : 2 : buf[1] = 'x';
134 : :
135 : : char hex[16];
136 : 2 : int i = 16;
137 : 2 : auto value = reinterpret_cast<uintptr_t>(ptr);
138 : :
139 : : do {
140 : 13 : hex[--i] = kHexDigits[value & 0xF];
141 : 13 : value >>= 4;
142 [ + + ]: 13 : } while (value != 0);
143 : :
144 : 2 : size_t n = static_cast<size_t>(16 - i);
145 : 2 : std::memcpy(buf + 2, hex + i, n);
146 : :
147 : 2 : return 2 + n;
148 : : }
149 : :
150 : 3 : size_t format_float_to(char* buf, size_t buflen, float value) noexcept {
151 : 3 : int len = std::snprintf(buf, buflen, "%g", static_cast<double>(value));
152 : :
153 [ + - + - : 3 : if VLIKELY (len > 0 && static_cast<size_t>(len) < buflen) {
+ - ]
154 : 3 : return static_cast<size_t>(len);
155 : : }
156 : :
157 : 0 : return 0;
158 : : }
159 : :
160 : 4 : size_t format_double_to(char* buf, size_t buflen, double value) noexcept {
161 : 4 : int len = std::snprintf(buf, buflen, "%g", value);
162 : :
163 [ + - + - : 4 : if VLIKELY (len > 0 && static_cast<size_t>(len) < buflen) {
+ - ]
164 : 4 : return static_cast<size_t>(len);
165 : : }
166 : :
167 : 0 : return 0;
168 : : }
169 : :
170 : : // NOLINTEND
171 : :
172 : : } // namespace detail
173 : : } // namespace format
174 : : } // namespace vlink
|