1 | // |
2 | // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. |
5 | // https://www.boost.org/LICENSE_1_0.txt |
6 | |
7 | #include <boost/locale/encoding.hpp> |
8 | #include <boost/locale/formatting.hpp> |
9 | #include <boost/locale/generator.hpp> |
10 | #include <boost/locale/info.hpp> |
11 | #include <boost/locale/localization_backend.hpp> |
12 | #include <boost/core/ignore_unused.hpp> |
13 | #include <ctime> |
14 | #include <iomanip> |
15 | #include <iostream> |
16 | #include <utility> |
17 | #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND |
18 | # ifndef NOMINMAX |
19 | # define NOMINMAX |
20 | # endif |
21 | # include <windows.h> |
22 | #endif |
23 | #include "../src/boost/locale/win32/lcid.hpp" |
24 | #include "boostLocale/test/tools.hpp" |
25 | #include "boostLocale/test/unit_test.hpp" |
26 | |
27 | template<typename CharType> |
28 | void test_by_char(const std::locale& l, std::string name, int lcid) |
29 | { |
30 | typedef std::basic_stringstream<CharType> ss_type; |
31 | |
32 | using namespace boost::locale; |
33 | |
34 | { |
35 | std::cout << "--- Testing as::posix" << std::endl; |
36 | ss_type ss; |
37 | ss.imbue(l); |
38 | |
39 | TEST(ss << 1045.45); |
40 | double n; |
41 | TEST(ss >> n); |
42 | TEST_EQ(n, 1045.45); |
43 | TEST_EQ(to_utf8(ss.str()), "1045.45" ); |
44 | } |
45 | |
46 | { |
47 | std::cout << "--- Testing as::number" << std::endl; |
48 | ss_type ss; |
49 | ss.imbue(l); |
50 | |
51 | ss << as::number; |
52 | TEST(ss << 1045.45); |
53 | double n; |
54 | TEST(ss >> n); |
55 | TEST_EQ(n, 1045.45); |
56 | |
57 | if(name == "ru_RU.UTF-8" ) { |
58 | BOOST_LOCALE_START_CONST_CONDITION |
59 | if(sizeof(CharType) == 1) // Space |
60 | TEST_EQ(to_utf8(ss.str()), "1 045,45" ); |
61 | else // Non-breaking space |
62 | TEST_EQ(to_utf8(ss.str()), |
63 | "1\xC2\xA0" |
64 | "045,45" ); |
65 | BOOST_LOCALE_END_CONST_CONDITION |
66 | } else |
67 | TEST_EQ(to_utf8(ss.str()), "1,045.45" ); |
68 | } |
69 | |
70 | { |
71 | std::cout << "--- Testing as::currency " << std::endl; |
72 | |
73 | ss_type ss; |
74 | ss.imbue(l); |
75 | |
76 | ss << as::currency; |
77 | TEST(ss << 1043.34); |
78 | |
79 | #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND |
80 | wchar_t buf[256]; |
81 | GetCurrencyFormatW(lcid, 0, L"1043.34" , nullptr, buf, 256); |
82 | TEST_EQ(to_utf8(ss.str()), to_utf8<wchar_t>(buf)); |
83 | #else |
84 | boost::ignore_unused(lcid); |
85 | #endif |
86 | } |
87 | |
88 | { |
89 | std::cout << "--- Testing as::date/time" << std::endl; |
90 | |
91 | const time_t a_date = 3600 * 24 * (31 + 4); // Feb 5th |
92 | const time_t a_time = 3600 * 15 + 60 * 33 + 13; // 15:33:13 |
93 | const time_t a_datetime = a_date + a_time; |
94 | |
95 | wchar_t time_buf[256]{}; |
96 | wchar_t date_buf[256]{}; |
97 | #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND |
98 | SYSTEMTIME st = {1970, 2, 5, 5, 15, 33, 13, 0}; |
99 | GetTimeFormatW(lcid, 0, &st, nullptr, time_buf, 256); |
100 | GetDateFormatW(lcid, 0, &st, nullptr, date_buf, 256); |
101 | #else |
102 | if(!time_buf[0]) |
103 | return; |
104 | #endif |
105 | const std::string expDate = to_utf8(utf_string: std::wstring(date_buf)); |
106 | const std::string expTime = to_utf8(utf_string: std::wstring(time_buf)); |
107 | |
108 | ss_type ss; |
109 | ss.imbue(l); |
110 | |
111 | ss << as::time_zone(id: "GMT" ); |
112 | |
113 | empty_stream(ss) << as::date << a_datetime; |
114 | TEST_EQ(to_utf8(ss.str()), expDate); |
115 | empty_stream(ss) << as::time << a_datetime; |
116 | TEST_EQ(to_utf8(ss.str()), expTime); |
117 | empty_stream(ss) << as::datetime << a_datetime; |
118 | TEST_EQ(to_utf8(ss.str()), expDate + " " + expTime); |
119 | empty_stream(ss) << as::time_zone(id: "GMT+01:00" ) << as::ftime(ascii_to<CharType>("%H" )) << a_datetime; |
120 | TEST_EQ(to_utf8(ss.str()), "16" ); |
121 | empty_stream(ss) << as::time_zone(id: "GMT+00:15" ) << as::ftime(ascii_to<CharType>("%M" )) << a_datetime; |
122 | TEST_EQ(to_utf8(ss.str()), "48" ); |
123 | } |
124 | } |
125 | |
126 | void test_date_time(const std::locale& l) // LCOV_EXCL_LINE |
127 | { |
128 | std::ostringstream ss; |
129 | ss.imbue(loc: l); |
130 | |
131 | ss << boost::locale::as::time_zone(id: "GMT" ); |
132 | |
133 | time_t a_date = 3600 * 24 * (31 + 4); // Feb 5th |
134 | time_t a_time = 3600 * 15 + 60 * 33; // 15:33:13 |
135 | time_t a_timesec = 13; |
136 | time_t a_datetime = a_date + a_time + a_timesec; |
137 | |
138 | const std::pair<std::string, std::string> testCases[] = { |
139 | {"a" , "Thu" }, {"A" , "Thursday" }, {"b" , "Feb" }, {"B" , "February" }, {"d" , "05" }, |
140 | {"D" , "02/05/70" }, {"e" , "5" }, {"h" , "Feb" }, {"H" , "15" }, {"I" , "03" }, |
141 | {"m" , "02" }, {"M" , "33" }, {"n" , "\n" }, {"p" , "PM" }, {"r" , "03:33:13 PM" }, |
142 | {"R" , "15:33" }, {"S" , "13" }, {"t" , "\t" }, {"y" , "70" }, {"Y" , "1970" }, |
143 | {"%" , "%" }}; |
144 | |
145 | for(const auto& patternAndResult : testCases) { |
146 | empty_stream(s&: ss) << boost::locale::as::ftime(format: "%" + patternAndResult.first) << a_datetime; |
147 | TEST_EQ(ss.str(), patternAndResult.second); |
148 | } |
149 | } // LCOV_EXCL_LINE |
150 | |
151 | BOOST_LOCALE_DISABLE_UNREACHABLE_CODE_WARNING |
152 | void test_main(int /*argc*/, char** /*argv*/) |
153 | { |
154 | #ifdef BOOST_LOCALE_NO_WINAPI_BACKEND |
155 | std::cout << "WinAPI Backend is not build... Skipping\n" ; |
156 | return; |
157 | #endif |
158 | boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); |
159 | mgr.select(backend_name: "winapi" ); |
160 | boost::locale::localization_backend_manager::global(mgr); |
161 | boost::locale::generator gen; |
162 | |
163 | for(const auto& name_lcid : {std::make_pair(x: "en_US.UTF-8" , y: 0x0409), |
164 | std::make_pair(x: "he_IL.UTF-8" , y: 0x040D), |
165 | std::make_pair(x: "ru_RU.UTF-8" , y: 0x0419)}) |
166 | { |
167 | const std::string name = name_lcid.first; |
168 | std::cout << "- " << name << " locale" << std::endl; |
169 | if(!has_win_locale(locale_name: name)) |
170 | std::cout << "-- not supported, skipping" << std::endl; // LCOV_EXCL_LINE |
171 | else { |
172 | const std::locale l = gen(name); |
173 | std::cout << "-- UTF-8" << std::endl; |
174 | test_by_char<char>(l, name, lcid: name_lcid.second); |
175 | std::cout << "-- UTF-16" << std::endl; |
176 | test_by_char<wchar_t>(l, name, lcid: name_lcid.second); |
177 | } |
178 | } |
179 | std::cout << "- Testing strftime" << std::endl; |
180 | test_date_time(l: gen("en_US.UTF-8" )); |
181 | } |
182 | |
183 | // boostinspect:noascii |
184 | |