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