Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:16

0001 //
0002 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
0003 // Copyright (c) 2022-2023 Alexander Grund
0004 //
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 
0008 #ifndef BOOST_LOCALE_FORMATTING_HPP_INCLUDED
0009 #define BOOST_LOCALE_FORMATTING_HPP_INCLUDED
0010 
0011 #include <boost/locale/time_zone.hpp>
0012 #include <boost/assert.hpp>
0013 #include <boost/utility/string_view.hpp>
0014 #include <cstdint>
0015 #include <cstring>
0016 #include <istream>
0017 #include <ostream>
0018 #include <string>
0019 #include <typeinfo>
0020 
0021 #ifdef BOOST_MSVC
0022 #    pragma warning(push)
0023 #    pragma warning(disable : 4275 4251 4231 4660)
0024 #endif
0025 
0026 namespace boost { namespace locale {
0027 
0028     /// \brief This namespace holds additional formatting
0029     /// flags that can be set using ios_info.
0030     namespace flags {
0031 
0032         /// Formatting flags, each one of them has corresponding manipulation
0033         /// in namespace \a as
0034         enum display_flags_type {
0035             posix = 0,
0036             number = 1,
0037             currency = 2,
0038             percent = 3,
0039             date = 4,
0040             time = 5,
0041             datetime = 6,
0042             strftime = 7,
0043             spellout = 8,
0044             ordinal = 9,
0045 
0046             display_flags_mask = 31,
0047 
0048             currency_default = 0 << 5,
0049             currency_iso = 1 << 5,
0050             currency_national = 2 << 5,
0051 
0052             currency_flags_mask = 3 << 5,
0053 
0054             time_default = 0 << 7,
0055             time_short = 1 << 7,
0056             time_medium = 2 << 7,
0057             time_long = 3 << 7,
0058             time_full = 4 << 7,
0059             time_flags_mask = 7 << 7,
0060 
0061             date_default = 0 << 10,
0062             date_short = 1 << 10,
0063             date_medium = 2 << 10,
0064             date_long = 3 << 10,
0065             date_full = 4 << 10,
0066             date_flags_mask = 7 << 10,
0067         };
0068 
0069         /// Special string patterns that can be used for text formatting
0070         enum pattern_type {
0071             datetime_pattern, ///< strftime like formatting
0072             time_zone_id      ///< time zone name
0073         };
0074 
0075         /// Special integer values that can be used for formatting
0076         enum value_type {
0077             domain_id ///< Domain code - for message formatting
0078         };
0079 
0080     } // namespace flags
0081 
0082     /// \brief This class holds external data beyond existing fmtflags that std::ios_base holds
0083     ///
0084     /// You should almost never create this object directly. Instead, you should access it via
0085     /// ios_info::get(stream_object) static member function. It automatically creates default formatting data for that
0086     /// stream
0087     class BOOST_LOCALE_DECL ios_info {
0088     public:
0089         /// \cond INTERNAL
0090         ios_info();
0091         ios_info(const ios_info&);
0092         ios_info& operator=(const ios_info&);
0093         ~ios_info();
0094         /// \endcond
0095 
0096         /// Get ios_info instance for specific stream object
0097         static ios_info& get(std::ios_base& ios);
0098 
0099         /// Set flags that define how to format data, e.g. number, spell, currency etc.
0100         void display_flags(uint64_t flags);
0101         /// Get flags that define how to format data, e.g. number, spell, currency etc.
0102         uint64_t display_flags() const;
0103 
0104         /// Set flags that define how to format currency
0105         void currency_flags(uint64_t flags);
0106         /// Get flags that define how to format currency
0107         uint64_t currency_flags() const;
0108 
0109         /// Set flags that define how to format date
0110         void date_flags(uint64_t flags);
0111         /// Get flags that define how to format date
0112         uint64_t date_flags() const;
0113 
0114         /// Set flags that define how to format time
0115         void time_flags(uint64_t flags);
0116         /// Get flags that define how to format time
0117         uint64_t time_flags() const;
0118 
0119         /// Set special message domain identification
0120         void domain_id(int);
0121         /// Get special message domain identification
0122         int domain_id() const;
0123 
0124         /// Set time zone for formatting dates and time
0125         void time_zone(const std::string&);
0126         /// Get time zone for formatting dates and time
0127         std::string time_zone() const;
0128 
0129         /// Set date/time pattern (strftime like)
0130         template<typename CharType>
0131         void date_time_pattern(const std::basic_string<CharType>& str)
0132         {
0133             date_time_pattern_set().set<CharType>(str);
0134         }
0135         /// Get date/time pattern (strftime like)
0136         template<typename CharType>
0137         std::basic_string<CharType> date_time_pattern() const
0138         {
0139             return date_time_pattern_set().get<CharType>();
0140         }
0141 
0142         /// \cond INTERNAL
0143         void on_imbue();
0144         /// \endcond
0145 
0146     private:
0147         class string_set;
0148 
0149         const string_set& date_time_pattern_set() const;
0150         string_set& date_time_pattern_set();
0151 
0152         class BOOST_LOCALE_DECL string_set {
0153         public:
0154             string_set();
0155             ~string_set();
0156             string_set(const string_set& other);
0157             string_set& operator=(string_set other);
0158             void swap(string_set& other);
0159 
0160             template<typename Char>
0161             void set(const boost::basic_string_view<Char> s)
0162             {
0163                 BOOST_ASSERT(!s.empty());
0164                 delete[] ptr;
0165                 ptr = nullptr;
0166                 type = &typeid(Char);
0167                 size = sizeof(Char) * s.size();
0168                 ptr = size ? new char[size] : nullptr;
0169                 memcpy(ptr, s.data(), size);
0170             }
0171 
0172             template<typename Char>
0173             std::basic_string<Char> get() const
0174             {
0175                 if(type == nullptr || *type != typeid(Char))
0176                     throw std::bad_cast();
0177                 std::basic_string<Char> result(size / sizeof(Char), Char(0));
0178                 memcpy(&result.front(), ptr, size);
0179                 return result;
0180             }
0181 
0182         private:
0183             const std::type_info* type;
0184             size_t size;
0185             char* ptr;
0186         };
0187 
0188         uint64_t flags_;
0189         int domain_id_;
0190         std::string time_zone_;
0191         string_set datetime_;
0192     };
0193 
0194     /// \brief This namespace includes all manipulators that can be used on IO streams
0195     namespace as {
0196         /// \defgroup manipulators I/O Stream manipulators
0197         ///
0198         /// @{
0199 
0200         /// Format values with "POSIX" or "C"  locale. Note, if locale was created with additional non-classic locale
0201         /// then These numbers may be localized
0202         inline std::ios_base& posix(std::ios_base& ios)
0203         {
0204             ios_info::get(ios).display_flags(flags::posix);
0205             return ios;
0206         }
0207 
0208         /// Format a number. Note, unlike standard number formatting, integers would be treated like real numbers when
0209         /// std::fixed or std::scientific manipulators were applied
0210         inline std::ios_base& number(std::ios_base& ios)
0211         {
0212             ios_info::get(ios).display_flags(flags::number);
0213             return ios;
0214         }
0215 
0216         /// Format currency, number is treated like amount of money
0217         inline std::ios_base& currency(std::ios_base& ios)
0218         {
0219             ios_info::get(ios).display_flags(flags::currency);
0220             return ios;
0221         }
0222 
0223         /// Format percent, value 0.3 is treated as 30%.
0224         inline std::ios_base& percent(std::ios_base& ios)
0225         {
0226             ios_info::get(ios).display_flags(flags::percent);
0227             return ios;
0228         }
0229 
0230         /// Format a date, number is treated as POSIX time
0231         inline std::ios_base& date(std::ios_base& ios)
0232         {
0233             ios_info::get(ios).display_flags(flags::date);
0234             return ios;
0235         }
0236 
0237         /// Format a time, number is treated as POSIX time
0238         inline std::ios_base& time(std::ios_base& ios)
0239         {
0240             ios_info::get(ios).display_flags(flags::time);
0241             return ios;
0242         }
0243 
0244         /// Format a date and time, number is treated as POSIX time
0245         inline std::ios_base& datetime(std::ios_base& ios)
0246         {
0247             ios_info::get(ios).display_flags(flags::datetime);
0248             return ios;
0249         }
0250 
0251         /// Create formatted date time, Please note, this manipulator only changes formatting mode,
0252         /// and not format itself, so you are probably looking for ftime manipulator
0253         inline std::ios_base& strftime(std::ios_base& ios)
0254         {
0255             ios_info::get(ios).display_flags(flags::strftime);
0256             return ios;
0257         }
0258 
0259         /// Spell the number, like "one hundred and ten"
0260         inline std::ios_base& spellout(std::ios_base& ios)
0261         {
0262             ios_info::get(ios).display_flags(flags::spellout);
0263             return ios;
0264         }
0265 
0266         /// Write an order of the number like 4th.
0267         inline std::ios_base& ordinal(std::ios_base& ios)
0268         {
0269             ios_info::get(ios).display_flags(flags::ordinal);
0270             return ios;
0271         }
0272 
0273         /// Set default currency formatting style -- national, like "$"
0274         inline std::ios_base& currency_default(std::ios_base& ios)
0275         {
0276             ios_info::get(ios).currency_flags(flags::currency_default);
0277             return ios;
0278         }
0279 
0280         /// Set ISO currency formatting style, like "USD", (requires ICU >= 4.2)
0281         inline std::ios_base& currency_iso(std::ios_base& ios)
0282         {
0283             ios_info::get(ios).currency_flags(flags::currency_iso);
0284             return ios;
0285         }
0286 
0287         /// Set national currency formatting style, like "$"
0288         inline std::ios_base& currency_national(std::ios_base& ios)
0289         {
0290             ios_info::get(ios).currency_flags(flags::currency_national);
0291             return ios;
0292         }
0293 
0294         /// set default (medium) time formatting style
0295         inline std::ios_base& time_default(std::ios_base& ios)
0296         {
0297             ios_info::get(ios).time_flags(flags::time_default);
0298             return ios;
0299         }
0300 
0301         /// set short time formatting style
0302         inline std::ios_base& time_short(std::ios_base& ios)
0303         {
0304             ios_info::get(ios).time_flags(flags::time_short);
0305             return ios;
0306         }
0307 
0308         /// set medium time formatting style
0309         inline std::ios_base& time_medium(std::ios_base& ios)
0310         {
0311             ios_info::get(ios).time_flags(flags::time_medium);
0312             return ios;
0313         }
0314 
0315         /// set long time formatting style
0316         inline std::ios_base& time_long(std::ios_base& ios)
0317         {
0318             ios_info::get(ios).time_flags(flags::time_long);
0319             return ios;
0320         }
0321 
0322         /// set full time formatting style
0323         inline std::ios_base& time_full(std::ios_base& ios)
0324         {
0325             ios_info::get(ios).time_flags(flags::time_full);
0326             return ios;
0327         }
0328 
0329         /// set default (medium) date formatting style
0330         inline std::ios_base& date_default(std::ios_base& ios)
0331         {
0332             ios_info::get(ios).date_flags(flags::date_default);
0333             return ios;
0334         }
0335 
0336         /// set short date formatting style
0337         inline std::ios_base& date_short(std::ios_base& ios)
0338         {
0339             ios_info::get(ios).date_flags(flags::date_short);
0340             return ios;
0341         }
0342 
0343         /// set medium date formatting style
0344         inline std::ios_base& date_medium(std::ios_base& ios)
0345         {
0346             ios_info::get(ios).date_flags(flags::date_medium);
0347             return ios;
0348         }
0349 
0350         /// set long date formatting style
0351         inline std::ios_base& date_long(std::ios_base& ios)
0352         {
0353             ios_info::get(ios).date_flags(flags::date_long);
0354             return ios;
0355         }
0356 
0357         /// set full date formatting style
0358         inline std::ios_base& date_full(std::ios_base& ios)
0359         {
0360             ios_info::get(ios).date_flags(flags::date_full);
0361             return ios;
0362         }
0363 
0364         /// \cond INTERNAL
0365         namespace detail {
0366             inline bool is_datetime_display_flags(const uint64_t display_flags)
0367             {
0368                 return (display_flags == flags::date || display_flags == flags::time || display_flags == flags::datetime
0369                         || display_flags == flags::strftime);
0370             }
0371 
0372             template<typename CharType>
0373             struct add_ftime {
0374                 std::basic_string<CharType> ftime;
0375 
0376                 void apply(std::basic_ios<CharType>& ios) const
0377                 {
0378                     ios_info::get(ios).date_time_pattern(ftime);
0379                     as::strftime(ios);
0380                 }
0381             };
0382 
0383             template<typename CharType>
0384             std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const add_ftime<CharType>& fmt)
0385             {
0386                 fmt.apply(out);
0387                 return out;
0388             }
0389 
0390             template<typename CharType>
0391             std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const add_ftime<CharType>& fmt)
0392             {
0393                 fmt.apply(in);
0394                 return in;
0395             }
0396 
0397         } // namespace detail
0398         /// \endcond
0399 
0400         /// Set strftime like formatting string
0401         ///
0402         /// Please note, formatting flags are very similar but not exactly the same as flags for C function strftime.
0403         /// Differences: some flags as "%e" do not add blanks to fill text up to two spaces, not all flags supported.
0404         ///
0405         /// Flags:
0406         /// -   "%a" -- Abbreviated  weekday (Sun.)
0407         /// -   "%A" -- Full weekday (Sunday)
0408         /// -   "%b" -- Abbreviated month (Jan.)
0409         /// -   "%B" -- Full month (January)
0410         /// -   "%c" -- Locale date-time format. **Note:** prefer using "as::datetime"
0411         /// -   "%d" -- Day of Month [01,31]
0412         /// -   "%e" -- Day of Month [1,31]
0413         /// -   "%h" -- Same as "%b"
0414         /// -   "%H" -- 24 clock hour [00,23]
0415         /// -   "%I" -- 12 clock hour [01,12]
0416         /// -   "%j" -- Day of year [1,366]
0417         /// -   "%m" -- Month [01,12]
0418         /// -   "%M" -- Minute [00,59]
0419         /// -   "%n" -- New Line
0420         /// -   "%p" -- AM/PM in locale representation
0421         /// -   "%r" -- Time with AM/PM, same as "%I:%M:%S %p"
0422         /// -   "%R" -- Same as "%H:%M"
0423         /// -   "%S" -- Second [00,61]
0424         /// -   "%t" -- Tab character
0425         /// -   "%T" -- Same as "%H:%M:%S"
0426         /// -   "%x" -- Local date representation. **Note:** prefer using "as::date"
0427         /// -   "%X" -- Local time representation. **Note:** prefer using "as::time"
0428         /// -   "%y" -- Year [00,99]
0429         /// -   "%Y" -- 4 digits year. (2009)
0430         /// -   "%Z" -- Time Zone
0431         /// -   "%%" -- Percent symbol
0432         ///
0433 
0434         template<typename CharType>
0435 #ifdef BOOST_LOCALE_DOXYGEN
0436         unspecified_type
0437 #else
0438         detail::add_ftime<CharType>
0439 #endif
0440         ftime(const std::basic_string<CharType>& format)
0441         {
0442             detail::add_ftime<CharType> fmt;
0443             fmt.ftime = format;
0444             return fmt;
0445         }
0446 
0447         /// See ftime(std::basic_string<CharType> const &format)
0448         template<typename CharType>
0449 #ifdef BOOST_LOCALE_DOXYGEN
0450         unspecified_type
0451 #else
0452         detail::add_ftime<CharType>
0453 #endif
0454         ftime(const CharType* format)
0455         {
0456             detail::add_ftime<CharType> fmt;
0457             fmt.ftime = format;
0458             return fmt;
0459         }
0460 
0461         /// \cond INTERNAL
0462         namespace detail {
0463             struct set_timezone {
0464                 std::string id;
0465             };
0466             template<typename CharType>
0467             std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const set_timezone& fmt)
0468             {
0469                 ios_info::get(out).time_zone(fmt.id);
0470                 return out;
0471             }
0472 
0473             template<typename CharType>
0474             std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const set_timezone& fmt)
0475             {
0476                 ios_info::get(in).time_zone(fmt.id);
0477                 return in;
0478             }
0479         } // namespace detail
0480         /// \endcond
0481 
0482         /// Set GMT time zone to stream
0483         inline std::ios_base& gmt(std::ios_base& ios)
0484         {
0485             ios_info::get(ios).time_zone("GMT");
0486             return ios;
0487         }
0488 
0489         /// Set local time zone to stream
0490         inline std::ios_base& local_time(std::ios_base& ios)
0491         {
0492             ios_info::get(ios).time_zone(time_zone::global());
0493             return ios;
0494         }
0495 
0496         /// Set time zone using \a id
0497         inline
0498 #ifdef BOOST_LOCALE_DOXYGEN
0499           unspecified_type
0500 #else
0501           detail::set_timezone
0502 #endif
0503           time_zone(const char* id)
0504         {
0505             detail::set_timezone tz;
0506             tz.id = id;
0507             return tz;
0508         }
0509 
0510         /// Set time zone using \a id
0511         inline
0512 #ifdef BOOST_LOCALE_DOXYGEN
0513           unspecified_type
0514 #else
0515           detail::set_timezone
0516 #endif
0517           time_zone(const std::string& id)
0518         {
0519             detail::set_timezone tz;
0520             tz.id = id;
0521             return tz;
0522         }
0523 
0524         /// @}
0525 
0526     } // namespace as
0527 
0528 }} // namespace boost::locale
0529 
0530 #ifdef BOOST_MSVC
0531 #    pragma warning(pop)
0532 #endif
0533 
0534 #endif