xref: /aosp_15_r20/external/pigweed/pw_string/type_to_string.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2019 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_string/type_to_string.h"
16 
17 #include <array>
18 #include <cmath>
19 #include <cstddef>
20 #include <cstring>
21 #include <limits>
22 
23 #include "lib/stdcompat/bit.h"
24 
25 namespace pw::string {
26 
IntToHexString(uint64_t value,span<char> buffer,uint_fast8_t min_width)27 StatusWithSize IntToHexString(uint64_t value,
28                               span<char> buffer,
29                               uint_fast8_t min_width) {
30   const uint_fast8_t digits = std::max(HexDigitCount(value), min_width);
31 
32   if (digits >= buffer.size()) {
33     return internal::HandleExhaustedBuffer(buffer);
34   }
35 
36   for (int i = static_cast<int>(digits) - 1; i >= 0; --i) {
37     buffer[static_cast<size_t>(i)] = "0123456789abcdef"[value & 0xF];
38     value >>= 4;
39   }
40 
41   buffer[digits] = '\0';
42   return StatusWithSize(digits);
43 }
44 
FloatAsIntToString(float value,span<char> buffer)45 StatusWithSize FloatAsIntToString(float value, span<char> buffer) {
46   // If it's finite and fits in an int64_t, print it as a rounded integer.
47   if (std::isfinite(value) &&
48       std::abs(value) <
49           static_cast<float>(std::numeric_limits<int64_t>::max())) {
50     return IntToString<int64_t>(static_cast<int64_t>(std::roundf(value)),
51                                 buffer);
52   }
53 
54   // Otherwise, print inf or NaN, if they fit.
55   if (const size_t written = 3 + std::signbit(value); written < buffer.size()) {
56     char* out = buffer.data();
57     if (std::signbit(value)) {
58       *out++ = '-';
59     }
60     std::memcpy(out, std::isnan(value) ? "NaN" : "inf", sizeof("NaN"));
61     return StatusWithSize(written);
62   }
63 
64   return internal::HandleExhaustedBuffer(buffer);
65 }
66 
BoolToString(bool value,span<char> buffer)67 StatusWithSize BoolToString(bool value, span<char> buffer) {
68   return CopyEntireStringOrNull(value ? "true" : "false", buffer);
69 }
70 
PointerToString(const void * pointer,span<char> buffer)71 StatusWithSize PointerToString(const void* pointer, span<char> buffer) {
72   if (pointer == nullptr) {
73     return CopyEntireStringOrNull(kNullPointerString, buffer);
74   }
75   return IntToHexString(reinterpret_cast<uintptr_t>(pointer), buffer);
76 }
77 
CopyEntireStringOrNull(std::string_view value,span<char> buffer)78 StatusWithSize CopyEntireStringOrNull(std::string_view value,
79                                       span<char> buffer) {
80   if (value.size() >= buffer.size()) {
81     return internal::HandleExhaustedBuffer(buffer);
82   }
83 
84   std::memcpy(buffer.data(), value.data(), value.size());
85   buffer[value.size()] = '\0';
86   return StatusWithSize(value.size());
87 }
88 
89 }  // namespace pw::string
90