Line data Source code
1 : // Copyright (c) 2011-2026 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify the to_string_literal templates.
21 : *
22 : * This file verifies that the to_string_literal template works as expected.
23 : */
24 :
25 : // snapdev
26 : //
27 : #include <snapdev/to_string_literal.h>
28 :
29 :
30 : // self
31 : //
32 : #include "catch_main.h"
33 :
34 :
35 : // C++
36 : //
37 : #include <iomanip>
38 :
39 :
40 :
41 : namespace
42 : {
43 :
44 : // convert a port number to a string at compile time
45 : //
46 : constexpr std::string_view g_decimal_zero = snapdev::integer_to_string_literal<0>.data(); // a special case
47 : constexpr std::string_view g_decimal_minus_one = snapdev::integer_to_string_literal<-1>.data();
48 : constexpr int const LOCAL_PORT = 9123;
49 : constexpr std::string_view g_port_decimal = snapdev::integer_to_string_literal<LOCAL_PORT>.data();
50 : constexpr std::string_view g_port_decimal_explicit = snapdev::integer_to_string_literal<LOCAL_PORT, 10>.data();
51 : constexpr std::string_view g_port_hexadecimal = snapdev::integer_to_string_literal<LOCAL_PORT, 16>.data();
52 : constexpr std::string_view g_port_hexadecimal_uppercase = snapdev::integer_to_string_literal<LOCAL_PORT, 16, true>.data();
53 : constexpr std::string_view g_port_octal = snapdev::integer_to_string_literal<LOCAL_PORT, 8>.data();
54 : constexpr std::string_view g_port_binary = snapdev::integer_to_string_literal<LOCAL_PORT, 2>.data();
55 :
56 : // TODO: we need to check all the integer types (char, short, int, long, long long and unsigned counter parts and special types supported by g++ a.k.a. __int128)
57 :
58 : constexpr std::string_view g_float_zero = snapdev::floating_point_to_string_literal<0.0f>.data();
59 : constexpr std::string_view g_double_zero = snapdev::floating_point_to_string_literal<0.0>.data();
60 : constexpr std::string_view g_double_double_zero = snapdev::floating_point_to_string_literal<0.0l>.data();
61 : constexpr std::string_view g_float_minus_one = snapdev::floating_point_to_string_literal<-1.0f>.data();
62 : constexpr std::string_view g_double_minus_one = snapdev::floating_point_to_string_literal<-1.0>.data();
63 : constexpr std::string_view g_double_double_minus_one = snapdev::floating_point_to_string_literal<-1.0l>.data();
64 : constexpr std::string_view g_double_value = snapdev::floating_point_to_string_literal<-1008410.000456>.data();
65 : constexpr float const CONSTANT_ROOT_TWO = 1.414213562373095048801688724209698078;
66 : constexpr double const CONSTANT_PI = 3.141592653589793238462643383279502884;
67 : constexpr long double const CONSTANT_E = 2.718281828459045235360287471352662497;
68 : constexpr std::string_view g_root_two = snapdev::floating_point_to_string_literal<CONSTANT_ROOT_TWO>.data();
69 : constexpr std::string_view g_pi = snapdev::floating_point_to_string_literal<CONSTANT_PI>.data();
70 : constexpr std::string_view g_e = snapdev::floating_point_to_string_literal<CONSTANT_E>.data();
71 :
72 : }
73 :
74 :
75 2 : CATCH_TEST_CASE("to_string_literal", "[string]")
76 : {
77 2 : CATCH_START_SECTION("integer_to_string_literal: verify integral literals")
78 : {
79 3 : CATCH_REQUIRE("0" == std::string(g_decimal_zero));
80 3 : CATCH_REQUIRE("-1" == std::string(g_decimal_minus_one));
81 :
82 1 : std::stringstream ds;
83 1 : ds << std::setbase(10) << LOCAL_PORT;
84 3 : CATCH_REQUIRE(ds.str() == std::string(g_port_decimal));
85 3 : CATCH_REQUIRE(ds.str() == std::string(g_port_decimal_explicit));
86 :
87 1 : std::stringstream hs;
88 1 : hs << std::setbase(16) << LOCAL_PORT;
89 3 : CATCH_REQUIRE(hs.str() == std::string(g_port_hexadecimal));
90 :
91 1 : std::stringstream hsu;
92 1 : hsu << std::uppercase << std::setbase(16) << LOCAL_PORT;
93 3 : CATCH_REQUIRE(hsu.str() == std::string(g_port_hexadecimal_uppercase));
94 :
95 1 : std::stringstream os;
96 1 : os << std::setbase(8) << LOCAL_PORT;
97 3 : CATCH_REQUIRE(os.str() == std::string(g_port_octal));
98 :
99 : // unfortunately, for some really odd reasons, the std::setbase()
100 : // is limited to 8, 10, and 16...
101 : //
102 1 : char binary[64] = {};
103 1 : std::size_t q(std::size(binary) - 1);
104 15 : for(auto p(LOCAL_PORT); p != 0; p /= 2)
105 : {
106 14 : --q;
107 14 : binary[q] = (p & 1) + '0';
108 : }
109 5 : CATCH_REQUIRE(std::string(binary + q) == std::string(g_port_binary));
110 1 : }
111 2 : CATCH_END_SECTION()
112 :
113 2 : CATCH_START_SECTION("floating_point_to_string_literal: verify float literals")
114 : {
115 1 : CATCH_REQUIRE("0.000000" == g_float_zero);
116 1 : CATCH_REQUIRE("0.000000000000000" == g_double_zero);
117 1 : CATCH_REQUIRE("0.000000000000000000" == g_double_double_zero);
118 1 : CATCH_REQUIRE("-1.000000" == g_float_minus_one);
119 1 : CATCH_REQUIRE("-1.000000000000000" == g_double_minus_one);
120 1 : CATCH_REQUIRE("-1.000000000000000000" == g_double_double_minus_one);
121 :
122 1 : std::stringstream value;
123 1 : value << std::setprecision(22) << -1008410.000456;
124 1 : CATCH_REQUIRE(value.str() == g_double_value);
125 :
126 1 : std::stringstream root_two;
127 1 : root_two << std::setprecision(7) << CONSTANT_ROOT_TWO;
128 3 : CATCH_REQUIRE(root_two.str() == std::string(g_root_two));
129 :
130 1 : std::stringstream pi;
131 1 : pi << std::setprecision(16) << CONSTANT_PI;
132 3 : CATCH_REQUIRE(pi.str() == std::string(g_pi));
133 :
134 1 : std::stringstream e;
135 1 : e << std::setprecision(19) << CONSTANT_E;
136 3 : CATCH_REQUIRE(e.str() == std::string(g_e));
137 :
138 : // we also want to check every single function validity; probably in a separate test
139 : //
140 : //snapdev::detail::floating_point_to_string_literal_impl<CONSTANT_ROOT_TWO, char> r;
141 : //std::cout << "r whole() = " << r.whole() << "\n";
142 : //std::cout << "r fractional_length() = " << r.fractional_length() << "\n";
143 : //std::cout << "r frac() = " << r.frac() << "\n";
144 : //std::cout << "r BUFFER_SIZE = " << r.BUFFER_SIZE << "\n";
145 : //std::cout << "r length() = " << r.length() << "\n";
146 : //std::cout << "r size() = " << r.size() << "\n";
147 : //char const * ptr = r;
148 : //for(std::size_t i(0); i < r.size(); ++i)
149 : //{
150 : //std::cout << "r char[" << i << "] = " << static_cast<int>(ptr[i]) << "\n";
151 : //}
152 :
153 1 : }
154 2 : CATCH_END_SECTION()
155 2 : }
156 :
157 :
158 : // vim: ts=4 sw=4 et
|