Boost.Locale
formatting.hpp
1//
2// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3// Copyright (c) 2022-2023 Alexander Grund
4//
5// Distributed under the Boost Software License, Version 1.0.
6// https://www.boost.org/LICENSE_1_0.txt
7
8#ifndef BOOST_LOCALE_FORMATTING_HPP_INCLUDED
9#define BOOST_LOCALE_FORMATTING_HPP_INCLUDED
10
11#include <boost/locale/time_zone.hpp>
12#include <boost/assert.hpp>
13#include <boost/utility/string_view.hpp>
14#include <cstdint>
15#include <cstring>
16#include <istream>
17#include <ostream>
18#include <string>
19#include <typeinfo>
20
21#ifdef BOOST_MSVC
22# pragma warning(push)
23# pragma warning(disable : 4275 4251 4231 4660)
24#endif
25
26namespace boost { namespace locale {
27
30 namespace flags {
31
35 posix = 0,
36 number = 1,
37 currency = 2,
38 percent = 3,
39 date = 4,
40 time = 5,
41 datetime = 6,
42 strftime = 7,
43 spellout = 8,
44 ordinal = 9,
45
46 display_flags_mask = 31,
47
48 currency_default = 0 << 5,
49 currency_iso = 1 << 5,
50 currency_national = 2 << 5,
51
52 currency_flags_mask = 3 << 5,
53
54 time_default = 0 << 7,
55 time_short = 1 << 7,
56 time_medium = 2 << 7,
57 time_long = 3 << 7,
58 time_full = 4 << 7,
59 time_flags_mask = 7 << 7,
60
61 date_default = 0 << 10,
62 date_short = 1 << 10,
63 date_medium = 2 << 10,
64 date_long = 3 << 10,
65 date_full = 4 << 10,
66 date_flags_mask = 7 << 10,
67 };
68
73 };
74
78 };
79
80 } // namespace flags
81
87 class BOOST_LOCALE_DECL ios_info {
88 public:
90 ios_info();
91 ios_info(const ios_info&);
92 ios_info& operator=(const ios_info&);
93 ~ios_info();
95
97 static ios_info& get(std::ios_base& ios);
98
100 void display_flags(uint64_t flags);
102 uint64_t display_flags() const;
103
105 void currency_flags(uint64_t flags);
107 uint64_t currency_flags() const;
108
110 void date_flags(uint64_t flags);
112 uint64_t date_flags() const;
113
115 void time_flags(uint64_t flags);
117 uint64_t time_flags() const;
118
120 void domain_id(int);
122 int domain_id() const;
123
125 void time_zone(const std::string&);
127 std::string time_zone() const;
128
130 template<typename CharType>
131 void date_time_pattern(const std::basic_string<CharType>& str)
132 {
133 date_time_pattern_set().set<CharType>(str);
134 }
136 template<typename CharType>
137 std::basic_string<CharType> date_time_pattern() const
138 {
139 return date_time_pattern_set().get<CharType>();
140 }
141
143 void on_imbue();
145
146 private:
147 class string_set;
148
149 const string_set& date_time_pattern_set() const;
150 string_set& date_time_pattern_set();
151
152 class BOOST_LOCALE_DECL string_set {
153 public:
154 string_set();
155 ~string_set();
156 string_set(const string_set& other);
157 string_set& operator=(string_set other);
158 void swap(string_set& other);
159
160 template<typename Char>
161 void set(const boost::basic_string_view<Char> s)
162 {
163 BOOST_ASSERT(!s.empty());
164 delete[] ptr;
165 ptr = nullptr;
166 type = &typeid(Char);
167 size = sizeof(Char) * s.size();
168 ptr = size ? new char[size] : nullptr;
169 memcpy(ptr, s.data(), size);
170 }
171
172 template<typename Char>
173 std::basic_string<Char> get() const
174 {
175 if(type == nullptr || *type != typeid(Char))
176 throw std::bad_cast();
177 std::basic_string<Char> result(size / sizeof(Char), Char(0));
178 memcpy(&result.front(), ptr, size);
179 return result;
180 }
181
182 private:
183 const std::type_info* type;
184 size_t size;
185 char* ptr;
186 };
187
188 uint64_t flags_;
189 int domain_id_;
190 std::string time_zone_;
191 string_set datetime_;
192 };
193
195 namespace as {
199
202 inline std::ios_base& posix(std::ios_base& ios)
203 {
204 ios_info::get(ios).display_flags(flags::posix);
205 return ios;
206 }
207
210 inline std::ios_base& number(std::ios_base& ios)
211 {
212 ios_info::get(ios).display_flags(flags::number);
213 return ios;
214 }
215
217 inline std::ios_base& currency(std::ios_base& ios)
218 {
219 ios_info::get(ios).display_flags(flags::currency);
220 return ios;
221 }
222
224 inline std::ios_base& percent(std::ios_base& ios)
225 {
226 ios_info::get(ios).display_flags(flags::percent);
227 return ios;
228 }
229
231 inline std::ios_base& date(std::ios_base& ios)
232 {
233 ios_info::get(ios).display_flags(flags::date);
234 return ios;
235 }
236
238 inline std::ios_base& time(std::ios_base& ios)
239 {
240 ios_info::get(ios).display_flags(flags::time);
241 return ios;
242 }
243
245 inline std::ios_base& datetime(std::ios_base& ios)
246 {
247 ios_info::get(ios).display_flags(flags::datetime);
248 return ios;
249 }
250
253 inline std::ios_base& strftime(std::ios_base& ios)
254 {
255 ios_info::get(ios).display_flags(flags::strftime);
256 return ios;
257 }
258
260 inline std::ios_base& spellout(std::ios_base& ios)
261 {
262 ios_info::get(ios).display_flags(flags::spellout);
263 return ios;
264 }
265
267 inline std::ios_base& ordinal(std::ios_base& ios)
268 {
269 ios_info::get(ios).display_flags(flags::ordinal);
270 return ios;
271 }
272
274 inline std::ios_base& currency_default(std::ios_base& ios)
275 {
276 ios_info::get(ios).currency_flags(flags::currency_default);
277 return ios;
278 }
279
281 inline std::ios_base& currency_iso(std::ios_base& ios)
282 {
283 ios_info::get(ios).currency_flags(flags::currency_iso);
284 return ios;
285 }
286
288 inline std::ios_base& currency_national(std::ios_base& ios)
289 {
290 ios_info::get(ios).currency_flags(flags::currency_national);
291 return ios;
292 }
293
295 inline std::ios_base& time_default(std::ios_base& ios)
296 {
297 ios_info::get(ios).time_flags(flags::time_default);
298 return ios;
299 }
300
302 inline std::ios_base& time_short(std::ios_base& ios)
303 {
304 ios_info::get(ios).time_flags(flags::time_short);
305 return ios;
306 }
307
309 inline std::ios_base& time_medium(std::ios_base& ios)
310 {
311 ios_info::get(ios).time_flags(flags::time_medium);
312 return ios;
313 }
314
316 inline std::ios_base& time_long(std::ios_base& ios)
317 {
318 ios_info::get(ios).time_flags(flags::time_long);
319 return ios;
320 }
321
323 inline std::ios_base& time_full(std::ios_base& ios)
324 {
325 ios_info::get(ios).time_flags(flags::time_full);
326 return ios;
327 }
328
330 inline std::ios_base& date_default(std::ios_base& ios)
331 {
332 ios_info::get(ios).date_flags(flags::date_default);
333 return ios;
334 }
335
337 inline std::ios_base& date_short(std::ios_base& ios)
338 {
339 ios_info::get(ios).date_flags(flags::date_short);
340 return ios;
341 }
342
344 inline std::ios_base& date_medium(std::ios_base& ios)
345 {
346 ios_info::get(ios).date_flags(flags::date_medium);
347 return ios;
348 }
349
351 inline std::ios_base& date_long(std::ios_base& ios)
352 {
353 ios_info::get(ios).date_flags(flags::date_long);
354 return ios;
355 }
356
358 inline std::ios_base& date_full(std::ios_base& ios)
359 {
360 ios_info::get(ios).date_flags(flags::date_full);
361 return ios;
362 }
363
365 namespace detail {
366 inline bool is_datetime_display_flags(const uint64_t display_flags)
367 {
368 return (display_flags == flags::date || display_flags == flags::time || display_flags == flags::datetime
369 || display_flags == flags::strftime);
370 }
371
372 template<typename CharType>
373 struct add_ftime {
374 std::basic_string<CharType> ftime;
375
376 void apply(std::basic_ios<CharType>& ios) const
377 {
378 ios_info::get(ios).date_time_pattern(ftime);
379 as::strftime(ios);
380 }
381 };
382
383 template<typename CharType>
384 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const add_ftime<CharType>& fmt)
385 {
386 fmt.apply(out);
387 return out;
388 }
389
390 template<typename CharType>
391 std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const add_ftime<CharType>& fmt)
392 {
393 fmt.apply(in);
394 return in;
395 }
396
397 } // namespace detail
399
433
434 template<typename CharType>
435#ifdef BOOST_LOCALE_DOXYGEN
436 unspecified_type
437#else
438 detail::add_ftime<CharType>
439#endif
440 ftime(const std::basic_string<CharType>& format)
441 {
442 detail::add_ftime<CharType> fmt;
443 fmt.ftime = format;
444 return fmt;
445 }
446
448 template<typename CharType>
449#ifdef BOOST_LOCALE_DOXYGEN
450 unspecified_type
451#else
452 detail::add_ftime<CharType>
453#endif
454 ftime(const CharType* format)
455 {
456 detail::add_ftime<CharType> fmt;
457 fmt.ftime = format;
458 return fmt;
459 }
460
462 namespace detail {
463 struct set_timezone {
464 std::string id;
465 };
466 template<typename CharType>
467 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const set_timezone& fmt)
468 {
469 ios_info::get(out).time_zone(fmt.id);
470 return out;
471 }
472
473 template<typename CharType>
474 std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const set_timezone& fmt)
475 {
476 ios_info::get(in).time_zone(fmt.id);
477 return in;
478 }
479 } // namespace detail
481
483 inline std::ios_base& gmt(std::ios_base& ios)
484 {
485 ios_info::get(ios).time_zone("GMT");
486 return ios;
487 }
488
490 inline std::ios_base& local_time(std::ios_base& ios)
491 {
493 return ios;
494 }
495
497 inline
498#ifdef BOOST_LOCALE_DOXYGEN
499 unspecified_type
500#else
501 detail::set_timezone
502#endif
503 time_zone(const char* id)
504 {
505 detail::set_timezone tz;
506 tz.id = id;
507 return tz;
508 }
509
511 inline
512#ifdef BOOST_LOCALE_DOXYGEN
513 unspecified_type
514#else
515 detail::set_timezone
516#endif
517 time_zone(const std::string& id)
518 {
519 detail::set_timezone tz;
520 tz.id = id;
521 return tz;
522 }
523
525
526 } // namespace as
527
528}} // namespace boost::locale
529
530#ifdef BOOST_MSVC
531# pragma warning(pop)
532#endif
533
534#endif
a printf like class that allows type-safe and locale aware message formatting
Definition: format.hpp:181
This class holds external data beyond existing fmtflags that std::ios_base holds.
Definition: formatting.hpp:87
void time_flags(uint64_t flags)
Set flags that define how to format time.
void domain_id(int)
Set special message domain identification.
void display_flags(uint64_t flags)
Set flags that define how to format data, e.g. number, spell, currency etc.
static ios_info & get(std::ios_base &ios)
Get ios_info instance for specific stream object.
void time_zone(const std::string &)
Set time zone for formatting dates and time.
uint64_t display_flags() const
Get flags that define how to format data, e.g. number, spell, currency etc.
int domain_id() const
Get special message domain identification.
uint64_t time_flags() const
Get flags that define how to format time.
uint64_t currency_flags() const
Get flags that define how to format currency.
std::string time_zone() const
Get time zone for formatting dates and time.
void date_time_pattern(const std::basic_string< CharType > &str)
Set date/time pattern (strftime like)
Definition: formatting.hpp:131
std::basic_string< CharType > date_time_pattern() const
Get date/time pattern (strftime like)
Definition: formatting.hpp:137
uint64_t date_flags() const
Get flags that define how to format date.
void currency_flags(uint64_t flags)
Set flags that define how to format currency.
void date_flags(uint64_t flags)
Set flags that define how to format date.
std::basic_ostream< CharType, TraitsType > & operator<<(std::basic_ostream< CharType, TraitsType > &out, const segment< Iterator > &seg)
Write the segment to the stream character by character.
Definition: segment.hpp:367
std::basic_istream< CharType > & operator>>(std::basic_istream< CharType > &in, date_time &t)
Definition: date_time.hpp:743
basic_format< char > format
Definition of char based format.
Definition: format.hpp:418
std::ios_base & posix(std::ios_base &ios)
Definition: formatting.hpp:202
std::ios_base & date_full(std::ios_base &ios)
set full date formatting style
Definition: formatting.hpp:358
unspecified_type ftime(const std::basic_string< CharType > &format)
Definition: formatting.hpp:440
std::ios_base & time_short(std::ios_base &ios)
set short time formatting style
Definition: formatting.hpp:302
std::ios_base & date_default(std::ios_base &ios)
set default (medium) date formatting style
Definition: formatting.hpp:330
std::ios_base & date_medium(std::ios_base &ios)
set medium date formatting style
Definition: formatting.hpp:344
std::ios_base & strftime(std::ios_base &ios)
Definition: formatting.hpp:253
std::ios_base & currency_national(std::ios_base &ios)
Set national currency formatting style, like "$".
Definition: formatting.hpp:288
std::ios_base & currency_iso(std::ios_base &ios)
Set ISO currency formatting style, like "USD", (requires ICU >= 4.2)
Definition: formatting.hpp:281
std::ios_base & currency_default(std::ios_base &ios)
Set default currency formatting style – national, like "$".
Definition: formatting.hpp:274
unspecified_type time_zone(const char *id)
Set time zone using id.
Definition: formatting.hpp:503
std::ios_base & date_long(std::ios_base &ios)
set long date formatting style
Definition: formatting.hpp:351
std::ios_base & datetime(std::ios_base &ios)
Format a date and time, number is treated as POSIX time.
Definition: formatting.hpp:245
std::ios_base & time_default(std::ios_base &ios)
set default (medium) time formatting style
Definition: formatting.hpp:295
std::ios_base & currency(std::ios_base &ios)
Format currency, number is treated like amount of money.
Definition: formatting.hpp:217
std::ios_base & time_long(std::ios_base &ios)
set long time formatting style
Definition: formatting.hpp:316
std::ios_base & number(std::ios_base &ios)
Definition: formatting.hpp:210
std::ios_base & local_time(std::ios_base &ios)
Set local time zone to stream.
Definition: formatting.hpp:490
std::ios_base & percent(std::ios_base &ios)
Format percent, value 0.3 is treated as 30%.
Definition: formatting.hpp:224
std::ios_base & spellout(std::ios_base &ios)
Spell the number, like "one hundred and ten".
Definition: formatting.hpp:260
std::ios_base & time(std::ios_base &ios)
Format a time, number is treated as POSIX time.
Definition: formatting.hpp:238
std::ios_base & date_short(std::ios_base &ios)
set short date formatting style
Definition: formatting.hpp:337
std::ios_base & ordinal(std::ios_base &ios)
Write an order of the number like 4th.
Definition: formatting.hpp:267
std::ios_base & time_full(std::ios_base &ios)
set full time formatting style
Definition: formatting.hpp:323
std::ios_base & time_medium(std::ios_base &ios)
set medium time formatting style
Definition: formatting.hpp:309
std::ios_base & date(std::ios_base &ios)
Format a date, number is treated as POSIX time.
Definition: formatting.hpp:231
std::ios_base & gmt(std::ios_base &ios)
Set GMT time zone to stream.
Definition: formatting.hpp:483
pattern_type
Special string patterns that can be used for text formatting.
Definition: formatting.hpp:70
@ datetime_pattern
strftime like formatting
Definition: formatting.hpp:71
@ time_zone_id
time zone name
Definition: formatting.hpp:72
value_type
Special integer values that can be used for formatting.
Definition: formatting.hpp:76
@ domain_id
Domain code - for message formatting.
Definition: formatting.hpp:77
display_flags_type
Definition: formatting.hpp:34
std::string global()
Get global time zone identifier. If empty, system time zone is used.