Sese Framework  2.3.0
A cross-platform framework
Loading...
Searching...
No Matches
Number.h
Go to the documentation of this file.
1// Copyright 2024 libsese
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://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,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
19
20#pragma once
21
24#include <sese/Util.h>
25#include <cmath>
26
27#ifdef SESE_PLATFORM_WINDOWS
28#pragma warning(disable: 4146)
29#endif
30
31namespace sese::text {
33class Number final : public NotInstantiable {
34public:
35 Number() = delete;
36
37 static std::string toHex(uint64_t number, bool upper_case = true) noexcept;
38
39 static std::string toHex(int64_t number, bool upper_case = true) noexcept;
40
41 static std::string toOct(uint64_t number) noexcept;
42
43 static std::string toOct(int64_t number) noexcept;
44
45 static std::string toBin(uint64_t number) noexcept;
46
47 static std::string toBin(int64_t number) noexcept;
48
49 static std::string toString(double number, uint16_t placeholder) noexcept;
50
51 template<typename T>
52 static void toString(StringBuilder &builder, T number, int radix, bool upper_case) noexcept {
53 if (number < 0) {
54 builder.append('-');
55 number = -number;
56 }
57 int count = 0;
58 constexpr auto DIGIT_UP = "0123456789ABCDEF";
59 constexpr auto DIGIT_DOWN = "0123456789abcdef";
60 const auto DIGIT = upper_case ? DIGIT_UP : DIGIT_DOWN;
61 do {
62 int index = number % radix;
63 builder.append(DIGIT[index]);
64 number /= radix;
65 count += 1;
66 } while (number > 0);
67
68 // Directly invert part of the memory in the builder
69 std::reverse(static_cast<char *>(builder.buf()) + builder.length() - count, static_cast<char *>(builder.buf()) + builder.length());
70 }
71
72 template<typename T>
73 static void toString(StringBuilder &builder, T number, uint16_t placeholder) noexcept {
74 auto int_part = static_cast<int64_t>(number);
75 double frac = number - int_part;
76 double rounding_factor = std::pow(10, placeholder);
77 auto rounded_part = static_cast<int64_t>(frac * rounding_factor);
78
79 if (static_cast<double>(rounded_part) >= rounding_factor) {
80 int_part += 1;
81 rounded_part -= static_cast<int64_t>(rounding_factor);
82 }
83
84 toString(builder, int_part, 10, true);
85 if (placeholder > 0) {
86 builder.append('.');
87 if (rounded_part < 0) {
88 rounded_part = -rounded_part;
89 }
90 toString(builder, rounded_part, 10, true);
91 auto len = number2StringLength(rounded_part, 10);
92 if (len < placeholder) {
93 builder.append(std::string(placeholder - len, '0'));
94 }
95 }
96 }
97
98private:
99 static std::string toStringWithNoLeadingZeros(const std::string &number) noexcept;
100};
101} // namespace sese::text