| // |
| // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| #ifndef BOOST_LOCALE_FORMATTING_HPP_INCLUDED |
| #define BOOST_LOCALE_FORMATTING_HPP_INCLUDED |
| |
| #include <boost/locale/config.hpp> |
| #ifdef BOOST_MSVC |
| # pragma warning(push) |
| # pragma warning(disable : 4275 4251 4231 4660) |
| #endif |
| #include <boost/cstdint.hpp> |
| #include <boost/locale/time_zone.hpp> |
| #include <ostream> |
| #include <istream> |
| #include <string> |
| #include <string.h> |
| #include <typeinfo> |
| |
| namespace boost { |
| namespace locale { |
| /// |
| /// \brief This namespace holds additional formatting |
| /// flags that can be set using ios_info. |
| /// |
| namespace flags { |
| /// |
| /// Formatting flags, each one of them has corresponding manipulation |
| /// in namespace \a as |
| /// |
| typedef enum { |
| posix = 0, |
| number = 1, |
| currency = 2, |
| percent = 3, |
| date = 4, |
| time = 5, |
| datetime = 6, |
| strftime = 7, |
| spellout = 8, |
| ordinal = 9, |
| |
| display_flags_mask = 31, |
| |
| currency_default = 0 << 5, |
| currency_iso = 1 << 5, |
| currency_national = 2 << 5, |
| |
| currency_flags_mask = 3 << 5, |
| |
| time_default = 0 << 7, |
| time_short = 1 << 7, |
| time_medium = 2 << 7, |
| time_long = 3 << 7, |
| time_full = 4 << 7, |
| time_flags_mask = 7 << 7, |
| |
| date_default = 0 << 10, |
| date_short = 1 << 10, |
| date_medium = 2 << 10, |
| date_long = 3 << 10, |
| date_full = 4 << 10, |
| date_flags_mask = 7 << 10, |
| |
| datetime_flags_mask = date_flags_mask | time_flags_mask |
| |
| } display_flags_type; |
| |
| /// |
| /// Special string patters that can be used |
| /// for text formatting |
| /// |
| typedef enum { |
| datetime_pattern, ///< strftime like formatting |
| time_zone_id ///< time zone name |
| } pattern_type; |
| |
| /// |
| /// Special integer values that can be used for formatting |
| /// |
| typedef enum { |
| domain_id ///< Domain code - for message formatting |
| } value_type; |
| |
| |
| } // flags |
| |
| /// |
| /// \brief This class holds an external data - beyond existing fmtflags that std::ios_base holds |
| /// |
| /// You should almost never create this object directly. Instead, you should access it via ios_info::get(stream_object) |
| /// static member function. It automatically creates default formatting data for that stream |
| /// |
| class BOOST_LOCALE_DECL ios_info { |
| public: |
| |
| /// \cond INTERNAL |
| |
| ios_info(); |
| ios_info(ios_info const &); |
| ios_info const &operator=(ios_info const &); |
| ~ios_info(); |
| |
| /// \endcond |
| |
| /// |
| /// Get ios_info instance for specific stream object |
| /// |
| static ios_info &get(std::ios_base &ios); |
| |
| /// |
| /// Set a flags that define a way for format data like number, spell, currency etc. |
| /// |
| void display_flags(uint64_t flags); |
| |
| /// |
| /// Set a flags that define how to format currency |
| /// |
| void currency_flags(uint64_t flags); |
| |
| /// |
| /// Set a flags that define how to format date |
| /// |
| void date_flags(uint64_t flags); |
| |
| /// |
| /// Set a flags that define how to format time |
| /// |
| void time_flags(uint64_t flags); |
| |
| /// |
| /// Set a flags that define how to format both date and time |
| /// |
| void datetime_flags(uint64_t flags); |
| |
| /// |
| /// Set special message domain identification |
| /// |
| void domain_id(int); |
| |
| /// |
| /// Set time zone for formatting dates and time |
| /// |
| void time_zone(std::string const &); |
| |
| |
| /// |
| /// Set date/time pattern (strftime like) |
| /// |
| template<typename CharType> |
| void date_time_pattern(std::basic_string<CharType> const &str) |
| { |
| string_set &s = date_time_pattern_set(); |
| s.set<CharType>(str.c_str()); |
| } |
| |
| |
| /// |
| /// Get a flags that define a way for format data like number, spell, currency etc. |
| /// |
| uint64_t display_flags() const; |
| |
| /// |
| /// Get a flags that define how to format currency |
| /// |
| uint64_t currency_flags() const; |
| |
| |
| /// |
| /// Get a flags that define how to format date |
| /// |
| uint64_t date_flags() const; |
| |
| /// |
| /// Get a flags that define how to format time |
| /// |
| uint64_t time_flags() const; |
| |
| /// |
| /// Get a flags that define how to format both date and time |
| /// |
| uint64_t datetime_flags() const; |
| |
| /// |
| /// Get special message domain identification |
| /// |
| int domain_id() const; |
| |
| /// |
| /// Get time zone for formatting dates and time |
| /// |
| std::string time_zone() const; |
| |
| /// |
| /// Get date/time pattern (strftime like) |
| /// |
| template<typename CharType> |
| std::basic_string<CharType> date_time_pattern() const |
| { |
| string_set const &s = date_time_pattern_set(); |
| return s.get<CharType>(); |
| } |
| |
| /// \cond INTERNAL |
| void on_imbue(); |
| /// \endcond |
| |
| private: |
| |
| class string_set; |
| |
| string_set const &date_time_pattern_set() const; |
| string_set &date_time_pattern_set(); |
| |
| class BOOST_LOCALE_DECL string_set { |
| public: |
| string_set(); |
| ~string_set(); |
| string_set(string_set const &other); |
| string_set const &operator=(string_set const &other); |
| void swap(string_set &other); |
| |
| template<typename Char> |
| void set(Char const *s) |
| { |
| delete [] ptr; |
| ptr = 0; |
| type=&typeid(Char); |
| Char const *end = s; |
| while(*end!=0) end++; |
| // if ptr = 0 it does not matter what is value of size |
| size = sizeof(Char)*(end - s+1); |
| ptr = new char[size]; |
| memcpy(ptr,s,size); |
| } |
| |
| template<typename Char> |
| std::basic_string<Char> get() const |
| { |
| if(type==0 || *type!=typeid(Char)) |
| throw std::bad_cast(); |
| std::basic_string<Char> result = reinterpret_cast<Char const *>(ptr); |
| return result; |
| } |
| |
| private: |
| std::type_info const *type; |
| size_t size; |
| char *ptr; |
| }; |
| |
| uint64_t flags_; |
| int domain_id_; |
| std::string time_zone_; |
| string_set datetime_; |
| |
| struct data; |
| data *d; |
| |
| }; |
| |
| |
| /// |
| /// \brief This namespace includes all manipulators that can be used on IO streams |
| /// |
| namespace as { |
| /// |
| /// \defgroup manipulators I/O Stream manipulators |
| /// |
| /// @{ |
| /// |
| |
| /// |
| /// Format values with "POSIX" or "C" locale. Note, if locale was created with additional non-classic locale then |
| /// These numbers may be localized |
| /// |
| |
| inline std::ios_base & posix(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::posix); |
| return ios; |
| } |
| |
| /// |
| /// Format a number. Note, unlike standard number formatting, integers would be treated like real numbers when std::fixed or |
| /// std::scientific manipulators were applied |
| /// |
| inline std::ios_base & number(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::number); |
| return ios; |
| } |
| |
| /// |
| /// Format currency, number is treated like amount of money |
| /// |
| inline std::ios_base & currency(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::currency); |
| return ios; |
| } |
| |
| /// |
| /// Format percent, value 0.3 is treated as 30%. |
| /// |
| inline std::ios_base & percent(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::percent); |
| return ios; |
| } |
| |
| /// |
| /// Format a date, number is treated as POSIX time |
| /// |
| inline std::ios_base & date(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::date); |
| return ios; |
| } |
| |
| /// |
| /// Format a time, number is treated as POSIX time |
| /// |
| inline std::ios_base & time(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::time); |
| return ios; |
| } |
| |
| /// |
| /// Format a date and time, number is treated as POSIX time |
| /// |
| inline std::ios_base & datetime(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::datetime); |
| return ios; |
| } |
| |
| /// |
| /// Create formatted date time, Please note, this manipulator only changes formatting mode, |
| /// and not format itself, so you are probably looking for ftime manipulator |
| /// |
| inline std::ios_base & strftime(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::strftime); |
| return ios; |
| } |
| |
| /// |
| /// Spell the number, like "one hundred and ten" |
| /// |
| inline std::ios_base & spellout(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::spellout); |
| return ios; |
| } |
| |
| /// |
| /// Write an order of the number like 4th. |
| /// |
| inline std::ios_base & ordinal(std::ios_base & ios) |
| { |
| ios_info::get(ios).display_flags(flags::ordinal); |
| return ios; |
| } |
| |
| /// |
| /// Set default currency formatting style -- national, like "$" |
| /// |
| inline std::ios_base & currency_default(std::ios_base & ios) |
| { |
| ios_info::get(ios).currency_flags(flags::currency_default); |
| return ios; |
| } |
| |
| /// |
| /// Set ISO currency formatting style, like "USD", (requires ICU >= 4.2) |
| /// |
| inline std::ios_base & currency_iso(std::ios_base & ios) |
| { |
| ios_info::get(ios).currency_flags(flags::currency_iso); |
| return ios; |
| } |
| |
| /// |
| /// Set national currency formatting style, like "$" |
| /// |
| inline std::ios_base & currency_national(std::ios_base & ios) |
| { |
| ios_info::get(ios).currency_flags(flags::currency_national); |
| return ios; |
| } |
| |
| /// |
| /// set default (medium) time formatting style |
| /// |
| inline std::ios_base & time_default(std::ios_base & ios) |
| { |
| ios_info::get(ios).time_flags(flags::time_default); |
| return ios; |
| } |
| |
| /// |
| /// set short time formatting style |
| /// |
| inline std::ios_base & time_short(std::ios_base & ios) |
| { |
| ios_info::get(ios).time_flags(flags::time_short); |
| return ios; |
| } |
| |
| /// |
| /// set medium time formatting style |
| /// |
| inline std::ios_base & time_medium(std::ios_base & ios) |
| { |
| ios_info::get(ios).time_flags(flags::time_medium); |
| return ios; |
| } |
| |
| /// |
| /// set long time formatting style |
| /// |
| inline std::ios_base & time_long(std::ios_base & ios) |
| { |
| ios_info::get(ios).time_flags(flags::time_long); |
| return ios; |
| } |
| |
| /// |
| /// set full time formatting style |
| /// |
| inline std::ios_base & time_full(std::ios_base & ios) |
| { |
| ios_info::get(ios).time_flags(flags::time_full); |
| return ios; |
| } |
| |
| /// |
| /// set default (medium) date formatting style |
| /// |
| inline std::ios_base & date_default(std::ios_base & ios) |
| { |
| ios_info::get(ios).date_flags(flags::date_default); |
| return ios; |
| } |
| |
| /// |
| /// set short date formatting style |
| /// |
| inline std::ios_base & date_short(std::ios_base & ios) |
| { |
| ios_info::get(ios).date_flags(flags::date_short); |
| return ios; |
| } |
| |
| /// |
| /// set medium date formatting style |
| /// |
| inline std::ios_base & date_medium(std::ios_base & ios) |
| { |
| ios_info::get(ios).date_flags(flags::date_medium); |
| return ios; |
| } |
| |
| /// |
| /// set long date formatting style |
| /// |
| inline std::ios_base & date_long(std::ios_base & ios) |
| { |
| ios_info::get(ios).date_flags(flags::date_long); |
| return ios; |
| } |
| |
| /// |
| /// set full date formatting style |
| /// |
| inline std::ios_base & date_full(std::ios_base & ios) |
| { |
| ios_info::get(ios).date_flags(flags::date_full); |
| return ios; |
| } |
| |
| |
| /// \cond INTERNAL |
| namespace details { |
| template<typename CharType> |
| struct add_ftime { |
| |
| std::basic_string<CharType> ftime; |
| |
| void apply(std::basic_ios<CharType> &ios) const |
| { |
| ios_info::get(ios).date_time_pattern(ftime); |
| as::strftime(ios); |
| } |
| |
| }; |
| |
| template<typename CharType> |
| std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,add_ftime<CharType> const &fmt) |
| { |
| fmt.apply(out); |
| return out; |
| } |
| |
| template<typename CharType> |
| std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,add_ftime<CharType> const &fmt) |
| { |
| fmt.apply(in); |
| return in; |
| } |
| |
| } |
| /// \endcond |
| |
| /// |
| /// Set strftime like formatting string |
| /// |
| /// Please note, formatting flags are very similar but not exactly the same as flags for C function strftime. |
| /// Differences: some flags as "%e" do not add blanks to fill text up to two spaces, not all flags supported. |
| /// |
| /// Flags: |
| /// - "%a" -- Abbreviated weekday (Sun.) |
| /// - "%A" -- Full weekday (Sunday) |
| /// - "%b" -- Abbreviated month (Jan.) |
| /// - "%B" -- Full month (January) |
| /// - "%c" -- Locale date-time format. **Note:** prefer using "as::datetime" |
| /// - "%d" -- Day of Month [01,31] |
| /// - "%e" -- Day of Month [1,31] |
| /// - "%h" -- Same as "%b" |
| /// - "%H" -- 24 clock hour [00,23] |
| /// - "%I" -- 12 clock hour [01,12] |
| /// - "%j" -- Day of year [1,366] |
| /// - "%m" -- Month [01,12] |
| /// - "%M" -- Minute [00,59] |
| /// - "%n" -- New Line |
| /// - "%p" -- AM/PM in locale representation |
| /// - "%r" -- Time with AM/PM, same as "%I:%M:%S %p" |
| /// - "%R" -- Same as "%H:%M" |
| /// - "%S" -- Second [00,61] |
| /// - "%t" -- Tab character |
| /// - "%T" -- Same as "%H:%M:%S" |
| /// - "%x" -- Local date representation. **Note:** prefer using "as::date" |
| /// - "%X" -- Local time representation. **Note:** prefer using "as::time" |
| /// - "%y" -- Year [00,99] |
| /// - "%Y" -- 4 digits year. (2009) |
| /// - "%Z" -- Time Zone |
| /// - "%%" -- Percent symbol |
| /// |
| |
| |
| template<typename CharType> |
| #ifdef BOOST_LOCALE_DOXYGEN |
| unspecified_type |
| #else |
| details::add_ftime<CharType> |
| #endif |
| ftime(std::basic_string<CharType> const &format) |
| { |
| details::add_ftime<CharType> fmt; |
| fmt.ftime=format; |
| return fmt; |
| } |
| |
| /// |
| /// See ftime(std::basic_string<CharType> const &format) |
| /// |
| template<typename CharType> |
| #ifdef BOOST_LOCALE_DOXYGEN |
| unspecified_type |
| #else |
| details::add_ftime<CharType> |
| #endif |
| ftime(CharType const *format) |
| { |
| details::add_ftime<CharType> fmt; |
| fmt.ftime=format; |
| return fmt; |
| } |
| |
| /// \cond INTERNAL |
| namespace details { |
| struct set_timezone { |
| std::string id; |
| }; |
| template<typename CharType> |
| std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,set_timezone const &fmt) |
| { |
| ios_info::get(out).time_zone(fmt.id); |
| return out; |
| } |
| |
| template<typename CharType> |
| std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,set_timezone const &fmt) |
| { |
| ios_info::get(in).time_zone(fmt.id); |
| return in; |
| } |
| } |
| /// \endcond |
| |
| /// |
| /// Set GMT time zone to stream |
| /// |
| inline std::ios_base &gmt(std::ios_base &ios) |
| { |
| ios_info::get(ios).time_zone("GMT"); |
| return ios; |
| } |
| |
| /// |
| /// Set local time zone to stream |
| /// |
| inline std::ios_base &local_time(std::ios_base &ios) |
| { |
| ios_info::get(ios).time_zone(time_zone::global()); |
| return ios; |
| } |
| |
| /// |
| /// Set time zone using \a id |
| /// |
| inline |
| #ifdef BOOST_LOCALE_DOXYGEN |
| unspecified_type |
| #else |
| details::set_timezone |
| #endif |
| time_zone(char const *id) |
| { |
| details::set_timezone tz; |
| tz.id=id; |
| return tz; |
| } |
| |
| /// |
| /// Set time zone using \a id |
| /// |
| inline |
| #ifdef BOOST_LOCALE_DOXYGEN |
| unspecified_type |
| #else |
| details::set_timezone |
| #endif |
| time_zone(std::string const &id) |
| { |
| details::set_timezone tz; |
| tz.id=id; |
| return tz; |
| } |
| |
| |
| /// |
| /// @} |
| /// |
| |
| } // as manipulators |
| |
| } // locale |
| } // boost |
| |
| #ifdef BOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| |
| |
| #endif |
| // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 |