/** -*- C++ -*- ** ** KAI C++ Compiler ** ** Copyright (C) 1996-2001 Intel Corp. All rights reserved. **/ /** ** Lib++ : The Modena C++ Standard Library, ** Version 2.5, January 1998 ** ** Copyright (c) 1996-1998 Modena Software Inc. **/ #ifndef __KAI_LOCALE #define __KAI_LOCALE #include #include #include //#include #include #include // for mbstate_t. #include // for struct tm. namespace std { // locale, facet, ctype are in localebase // ************* CODECVT FACET *********************** class codecvt_base { public: enum result { ok = 0, partial, error, noconv }; }; template class codecvt : public locale::facet, public codecvt_base { public: typedef internT intern_type; typedef externT extern_type; typedef stateT state_type; explicit codecvt(size_t refs = 0) : locale::facet(refs) { } result out(state_type& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_limit, externT*& to_next) const { return do_out(state, from, from_end, from_next, to, to_limit, to_next); } result unshift(stateT& state, externT* to, externT* to_limit, externT*& to_next) const { return do_unshift(state, to, to_limit, to_next); } result in(state_type& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_limit, internT*& to_next) const { return do_in(state, from, from_end, from_next, to, to_limit, to_next); } int encoding() const MSIPL_THROW { return do_encoding(); } bool always_noconv() const MSIPL_THROW { return do_always_noconv(); } int length(const state_type& state, const externT* from, const externT* from_end, size_t max) const { return do_length(state, from, from_end, max); } int max_length() const MSIPL_THROW { return do_max_length(); } static locale::id id; protected: ~codecvt() { } // virtual virtual result do_out(state_type&, const internT*, const internT*, const internT*&, externT*, externT*, externT*& ) const; virtual result do_in(state_type&, const externT*, const externT*, const externT*&, internT*, internT*, internT*&) const; virtual result do_unshift(state_type&, externT*, externT*, externT*&) const; virtual int do_encoding() const MSIPL_THROW { return sizeof(internT); } virtual bool do_always_noconv() const MSIPL_THROW { return false; } virtual int do_length(const state_type&, externT*, const externT*, size_t) const; virtual int do_max_length() const MSIPL_THROW { return 1; } }; template locale::id codecvt::id; template int codecvt::do_length(const state_type& s, externT* from, const externT* from_end, size_t max) const { size_t flen = from_end-from; return max < flen ? max : flen; } // This class does not do anything, but it should. -- dcn 28 Jan 1999. template class codecvt_byname : public codecvt { public: explicit codecvt_byname(const char*, size_t refs = 0) : codecvt(refs) { } protected: ~codecvt_byname(); }; template codecvt_byname::~codecvt_byname() { } #if KAI_WCHAR_T template<> class codecvt : public locale::facet, public codecvt_base { // friend class locale::imp; public: typedef wchar_t from_type; typedef char to_type; typedef mbstate_t state_type; typedef from_type intern_type; typedef to_type extern_type; protected: virtual codecvt_base::result do_out(state_type& state, const from_type* from, const from_type* from_end, const from_type*& from_next, to_type* to, to_type* to_limit, to_type*& to_next) const; virtual codecvt_base::result do_unshift(state_type& state, to_type* to, to_type* to_limit, to_type*& to_next) const; virtual codecvt_base::result do_in(state_type& state, const to_type* from, const to_type* from_end, const to_type*& from_next, from_type* to, from_type* to_limit, from_type*& to_next) const; virtual int do_encoding() const MSIPL_THROW { return sizeof(intern_type); } virtual bool do_always_noconv() const MSIPL_THROW { return false; } // For wide characters, conversion is required w.r.t. external characters (bytes). virtual int do_length(const state_type& state, const from_type* from, const from_type* from_end, size_t max) const ; virtual int do_max_length() const MSIPL_THROW { return MB_CUR_MAX; } public: codecvt_base::result out(state_type& state, const from_type* from, const from_type* from_end, const from_type*& from_next, to_type* to, to_type* to_limit, to_type*& to_next) const { return do_out(state, from, from_end, from_next, to, to_limit, to_next); } codecvt_base::result unshift(state_type& state, to_type* to, to_type* to_limit, to_type*& to_next) const { return do_unshift(state, to, to_limit, to_next); } codecvt_base::result in(state_type& state, const to_type* from, const to_type* from_end, const to_type*& from_next, from_type* to, from_type* to_limit, from_type*& to_next) const { return do_in(state, from, from_end, from_next, to, to_limit, to_next); } int encoding() const MSIPL_THROW { return do_encoding(); } bool always_noconv() const MSIPL_THROW { return do_always_noconv (); } int length(const state_type& state, const from_type* from, const from_type* from_end, size_t max) const { return do_length(state, from, from_end, max); } int max_length() const MSIPL_THROW { return do_max_length(); } static locale::id id; explicit codecvt(size_t refs = 0) : locale::facet(refs) { } protected: ~codecvt () { } }; #endif /* KAI_WCHAR_T */ template<> class codecvt : public locale::facet, public codecvt_base { public: typedef mbstate_t state_type; typedef char intern_type; typedef char extern_type; explicit codecvt(size_t refs = 0) : locale::facet(refs) { } result out(state_type& state, const intern_type* from, const intern_type* from_end, const intern_type*& from_next, extern_type* to, extern_type* to_limit, extern_type*& to_next) const { return do_out(state, from, from_end, from_next, to, to_limit, to_next); } result unshift(state_type& state, extern_type* to, extern_type* to_limit, extern_type*& to_next) const { return do_unshift(state, to, to_limit, to_next); } result in(state_type& state, const extern_type* from, const extern_type* from_end, const extern_type*& from_next, intern_type* to, intern_type* to_limit, intern_type*& to_next) const { return do_in(state, from, from_end, from_next, to, to_limit, to_next); } int encoding() const MSIPL_THROW { return do_encoding(); } bool always_noconv() const MSIPL_THROW { return do_always_noconv (); } int length(const state_type& state, const intern_type* from, const intern_type* from_end, size_t max) const { return do_length(state, from, from_end, max); } int max_length() const MSIPL_THROW { return do_max_length(); } static locale::id id; protected: ~codecvt () { } virtual result do_out(state_type& state, const intern_type* from, const intern_type* from_end, const intern_type*& from_next, extern_type* to, extern_type* to_limit, extern_type*& to_next) const; virtual result do_unshift(state_type& state, extern_type* to, extern_type* to_limit, extern_type*& to_next) const; virtual result do_in(state_type& state, const extern_type* from, const extern_type* from_end, const extern_type*& from_next, intern_type* to, intern_type* to_limit, intern_type*& to_next) const; virtual int do_encoding() const MSIPL_THROW { return sizeof(intern_type); } virtual bool do_always_noconv() const MSIPL_THROW { return true; } virtual int do_length(const state_type& state, const intern_type* from, const intern_type* from_end, size_t max)const; virtual int do_max_length() const MSIPL_THROW { return 1; } }; } // namespace std namespace __kai { // // Function convert_locale_string is used to convert strings returned by localelconv // to a basic_string. The current implementation presumes that the strings // are part of the basic character set (not multibyte). // template std::basic_string convert_locale_string( const char * src ) { std::basic_string result; size_t _n = std::strlen(src); result.resize( _n ); for( size_t _k=0; _k<_n; ++_k ) { result[_k] = src[_k]; } return result; } // Specialization for sake of speed. template<> inline std::basic_string convert_locale_string( const char * src ) { return std::basic_string(src); } template std::basic_string convert_locale_string( const std::basic_string& src ) { return convert_locale_string(src.c_str()); } // Specialization for sake of speed. template<> inline std::basic_string convert_locale_string( const std::basic_string& src ) { return src; } // // Function convert_numeric_string is used to convert a string containing the numeric part // of money into a C string. The current implementation presumes that all characters // in a number are part of the basic character set (not multibyte). // template void convert_numeric_string( char * dst, const std::basic_string& src ) { size_t _n = src.size(); for( size_t _k=0; _k<_n; ++_k ) { dst[_k] = src[_k]; } } // Specialization for sake of speed. template<> inline void convert_numeric_string( char * dst, const std::basic_string& src ) { std::memcpy( dst, src.c_str(), src.size()+1 ); } } // namespace __kai namespace std { // ************ NUMERIC FACETS ************************* template > class num_get : public locale::facet { typedef ios_base::iostate iostate; public: typedef charT char_type; typedef InputIterator iter_type; explicit num_get(size_t refs = 0) : locale::facet(refs) { } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, bool& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, long& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, unsigned short& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, unsigned int& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, unsigned long& v) const { return do_get(from, end, f, state, v); } #if __KAI_LONG_LONG iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, __long_long& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, unsigned __long_long& v) const { return do_get(from, end, f, state, v); } #endif /* __KAI_LONG_LONG */ iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, float& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, double& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, long double& v) const { return do_get(from, end, f, state, v); } iter_type get(iter_type from, iter_type end, ios_base& f, iostate& state, void*& v) const { return do_get(from, end, f, state, v); } static locale::id id; protected: ~num_get() { } virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, bool& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, unsigned short& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, unsigned int& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, unsigned long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, float& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, double& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, long double& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, void*& v) const; #if __KAI_LONG_LONG virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, __long_long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, iostate& state, unsigned __long_long& v) const; #endif /* __KAI_LONG_LONG */ private: static unsigned long kai_scan_integral_type(iter_type&, iter_type&, ios_base&, int& radix, bool signed_value, unsigned long); static bool scan_float_type(iter_type&, iter_type&, ios_base&, char*) ; #if __KAI_LONG_LONG static unsigned __long_long kai_scan_long_long_type(iter_type&, iter_type&, ios_base&, int &, int, unsigned __long_long); #endif /* __KAI_LONG_LONG */ }; template locale::id num_get::id; template > class num_put : public locale::facet { typedef ios_base::iostate iostate; //typedef size_t size_type; public: typedef charT char_type; typedef OutputIterator iter_type; public: explicit num_put(size_t refs = 0) : locale::facet (refs) { } iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const { return do_put(s, f, fill, v); } iter_type put(iter_type s, ios_base& f, char_type fill, long v) const { return do_put(s, f, fill, v); } iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long v) const { return do_put(s, f, fill, v); } #if __KAI_LONG_LONG iter_type put(iter_type s, ios_base& f, char_type fill, __long_long v) const { return do_put(s, f, fill, v); } iter_type put(iter_type s, ios_base& f, char_type fill, unsigned __long_long v) const {return do_put(s, f, fill, v);} #endif /* __LONG_LONG */ iter_type put(iter_type s, ios_base& f, char_type fill, double v)const { return do_put(s, f, fill, v); } iter_type put(iter_type s, ios_base& f, char_type fill, long double v) const { return do_put(s, f, fill, v); } iter_type put(iter_type s, ios_base& f, char_type fill, void* v) const { return do_put(s, f, fill, v); } static locale::id id; protected: ~num_put() { } virtual iter_type do_put(iter_type, ios_base&, char_type fill, bool v) const; virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, long v) const { char buff[200] = "", fmt[7] = ""; int_fmt(fmt, 'd', io.flags()); return print_integral_type(begin, io, fill, buff, sprintf(buff, fmt, v)); } virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, unsigned long v) const { char buff[200] = "", fmt[7] = ""; int_fmt(fmt, 'u', io.flags()); return print_integral_type(begin, io, fill, buff, sprintf(buff, fmt, v)); } virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, double v) const { char buff[200] = "", fmt[8] = ""; size_t prec = io.precision() <= 0 && ! (io.flags() & ios_base::fixed) ? 6 : io.precision(); int MAX_CHAR = numeric_limits::max(); int pre = MAX_CHAR < prec ? MAX_CHAR : prec; float_fmt(fmt, '\0', io); return print_float_type(begin, io, fill, buff, prec - pre, sprintf(buff, fmt, pre, v)); } virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, long double v) const { char buff[200] = "", fmt[9] = ""; size_t prec = io.precision () <= 0 && ! (io.flags () & ios_base::fixed) ? 6 : io.precision (); int MAX_CHAR = numeric_limits::max (); int pre = MAX_CHAR < prec ? MAX_CHAR : prec; float_fmt (fmt, 'L', io); return (print_float_type(begin, io, fill, buff, prec - pre, sprintf(buff, fmt, pre, v))); } virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, void* v) const; #if __KAI_LONG_LONG virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, __long_long v) const { char buff[200] = "", fmt[7] = ""; int_fmt(fmt, 'd', io.flags(), true); return print_integral_type(begin, io, fill, buff, sprintf(buff, fmt, v)); } virtual iter_type do_put(iter_type begin, ios_base& io, char_type fill, unsigned __long_long v) const { char buff[200] = "", fmt[7] = ""; int_fmt(fmt, 'u', io.flags(), true); return print_integral_type(begin, io, fill, buff, sprintf(buff, fmt, v)); } #endif /* __KAI_LONG_LONG */ private: static iter_type print_integral_type(iter_type beg, ios_base& io, char_type fill, char* buf, size_t n); static iter_type print_float_type(iter_type beg, ios_base& io, char_type fill, char* buf, size_t nz, size_t n); static void int_fmt(char* fmt, char type, ios_base::fmtflags flag, bool is_long_long=false); static void float_fmt(char* fmt, char type, ios_base& io); }; template locale::id num_put::id; template class numpunct : public locale::facet { public: typedef charT char_type; typedef basic_string string_type; explicit numpunct(size_t refs = 0) : locale::facet(refs) { init("C"); } char_type decimal_point() const { return do_decimal_point(); } char_type thousands_sep() const { return do_thousands_sep(); } string grouping() const { return do_grouping (); } string_type truename() const { return do_truename(); } string_type falsename() const { return do_falsename(); } static locale::id id; protected: ~numpunct() { } friend class __kai::localeimp; explicit numpunct(const char* name, size_t refs = 0) : locale::facet (refs) { init(name); } virtual char_type do_decimal_point() const { return dec_pt; } virtual char_type do_thousands_sep() const { return thou_sep; } virtual string do_grouping() const { return grp; } virtual string_type do_truename() const { return name_true; } virtual string_type do_falsename() const { return name_false; } private: void init (const char* name) { const char* old_name = setlocale(LC_ALL, 0); if (setlocale(LC_NUMERIC, name) != 0) { struct lconv* lptr = localeconv(); dec_pt = lptr->decimal_point[0]; thou_sep = lptr->thousands_sep[0]; name_true = __kai::convert_locale_string( "true" ); name_false = __kai::convert_locale_string( "false" ); grp = lptr->grouping; } else { runtime_error::__throw("Invalid locale name\n"); } setlocale(LC_ALL, old_name); } char_type dec_pt; char_type thou_sep; string grp; string_type name_true; string_type name_false; }; template locale::id numpunct::id; template class numpunct_byname : public numpunct { public: explicit numpunct_byname(const char* name, size_t refs = 0) : numpunct(name, refs) { } protected: ~numpunct_byname() { } }; template num_put::iter_type num_put::do_put(iter_type begin, ios_base& io, char_type fill, void* v) const { char buff[200] = "", fmt[7] = ""; int_fmt (fmt, 'p', io.flags()); size_t n = sprintf(buff, fmt, v); char *cur = buff; size_t pad = io.width () > n ? io.width () - n : 0; ios_base::fmtflags flag = io.flags() & ios_base::adjustfield; if (flag != ios_base::left) for ( ; pad > 0; --pad, ++begin) *begin = fill; for ( ; n > 0; n--, ++begin, ++cur) *begin = *cur; for ( ; pad > 0; --pad, ++begin) *begin = fill; io.width(0); return begin; } template num_put::iter_type num_put::do_put(iter_type iter, ios_base& io, char_type fill, bool v) const { const locale& loc = io.getloc(); const numpunct& punct = use_facet >(loc); if (io.flags () & ios_base::boolalpha) { const basic_string str(v ? punct.truename() : punct.falsename()); size_t cnt = 0; while (cnt < str.size()) { *iter++ = str[cnt]; cnt ++; } } else { *iter++ = (v ? '1' : '0'); } return iter; } #ifdef MSIPL_WCHAR #define __W(str) ct.widen(str) #else #define __W(str) (str) #endif template num_put::iter_type num_put:: print_integral_type(iter_type begin, ios_base& io, char_type fill, char *buff, size_t n) { size_t p = (*buff == '+' || *buff == '-') ? 1 : *buff == '0' && (buff[1] == 'x' || buff[1] == 'X')? 2 : *buff != '0' ? 0 : * (buff+1) != '\0'? 1:0; const numpunct& punct = use_facet >(io.getloc()); const char_type thou_sep = punct.thousands_sep(); string _mslstrg = punct.grouping(); const char* G = _mslstrg.c_str(); size_t index = n; const int MAX_CHAR = numeric_limits::max(); for (; *G !=MAX_CHAR && *G < (index - p) && *G > '\0'; ) { index -= *G; char_traits::move(&buff[index+1] , &buff[index] , n + 1 - index); buff[index] = ','; ++n; if ('\0' < G[1]) ++G; } size_t pad = io.width() > n ? io.width() - n : 0; ios_base::fmtflags flag = io.flags() & ios_base::adjustfield; if (flag == ios_base::internal) for ( ; p > 0; --p, --n, ++begin, ++buff) *begin = __W(*buff); if (flag != ios_base::left) for ( ; pad > 0; --pad, ++begin) *begin = fill; for ( ; n > 0; ++begin, ++buff, --n) if (*buff == ',') *begin = thou_sep; else *begin = __W(*buff); io.width(0); for ( ; pad > 0; --pad, ++begin) *begin = fill; return begin; } template void num_put::int_fmt(char* fmt, char type, ios_base::fmtflags flag, bool is_long_long) { char *fmt1 = fmt; *fmt1++ = '%'; if (type == 'p') *fmt1++ = 'p'; else { if (flag & ios_base::showpos) *fmt1++ = '+'; if (flag & ios_base::showbase) *fmt1++ = '#'; #if !(defined(__alpha) && defined(__osf__)) if (is_long_long) *fmt1++ = 'l'; #endif *fmt1++ = 'l'; ios_base::fmtflags Bflag = flag & ios_base::basefield; *fmt1++ = Bflag == ios_base::oct ? 'o' : (Bflag != ios_base::hex ? type : (flag & ios_base::uppercase ? 'X' : 'x')); } *fmt1++ = '\0'; } template num_put::iter_type num_put::print_float_type (iter_type begin, ios_base& io, char_type fill, char *buff, size_t nz, size_t n) { size_t s = *buff == '+' || *buff == '-' ? 1 : 0; const numpunct& punct = use_facet >(io.getloc()); const char_type thou_sep = punct.thousands_sep(); string _mslstrg = punct.grouping(); const char* G = _mslstrg.c_str(); char * p = (char*)memchr (buff, localeconv()->decimal_point[0], n); size_t index; if (!p) index = n; else index = p - buff; char * p1 = buff; for (int k = index; k > 0; k--) ++p1; const int MAX_CHAR = numeric_limits::max(); const ctype& ct = use_facet >(io.getloc()); for (; *G !=MAX_CHAR && *G < (index - s) && *G > '\0'; ) { index -= *G; char_traits::move(&buff[index+1] , &buff[index] , n + 1 - index); buff[index] = ','; ++n; ++p1; if (p) ++p; if ('\0' < G[1]) ++G; } int pad = io.width() > n + nz ? io.width() - n - nz: 0; ios_base::fmtflags flag = io.flags() & ios_base::adjustfield; if ((*buff == '+' || *buff == '-') && (io.flags() & ios_base::internal)) { *begin = __W(*buff); ++begin; --n; ++buff; } if (flag != ios_base::left) for ( ; pad > 0; --pad, ++begin) *begin = fill; for ( ; buff != p1; ++begin, ++buff, --n) if (*buff == ',') *begin = thou_sep; else *begin = __W(*buff); if (p) { *begin = use_facet >(io.getloc()).decimal_point(); ++begin; ++buff; --n; } if (p = (char*)memchr(buff, 'e', n)) { for (;buff != p; begin++, --n) { *begin = __W(*buff); buff++; } for (; nz > 0; --nz) *begin = __W('0'); *begin = io.flags() & ios_base::uppercase ? 'E' : 'e'; ++begin; ++buff; --n; } for ( ;n > 0; --n, ++begin) { *begin = __W(*buff); ++buff; } for ( ;nz > 0; --nz, ++begin) *begin = __W('0'); io.width (0); for ( ; pad > 0; --pad, ++begin) *begin = fill; return begin; } #undef __W template void num_put::float_fmt(char* fmt, char type, ios_base& io) { char *fmt1 = fmt; ios_base::fmtflags flag = io.flags(); *fmt1++ = '%'; if (flag & ios_base::showpos) *fmt1++ = '+'; if (flag & ios_base::showpoint) *fmt1++ = '#'; *fmt1++ = '.'; *fmt1++ = '*' ; if (type != '\0') *fmt1++ = type; ios_base::fmtflags Fflag = flag & ios_base::floatfield; *fmt1++ = Fflag == ios_base::fixed ? 'f' : Fflag == ios_base::scientific ? 'e' : 'g'; *fmt1++ = '\0'; } #ifdef MSIPL_WCHAR #define __N(str) ct.narrow(str, 0) #else #define __N(str) (str) #endif template unsigned long num_get:: kai_scan_integral_type (iter_type &begin, iter_type &end, ios_base& io, int& radix, bool signed_value, unsigned long effective_bits) { typedef char_traits straits_type; const locale& loc = io.getloc (); const numpunct& punct = use_facet >(loc); const string grp( punct.grouping() ); const char thou_sep( punct.thousands_sep() ); unsigned long error_value = effective_bits >> signed_value; int seps [30]; int num_seps = 0; int digits_seen = 0; const int Size = grp.size(); bool negative = false; int leading_zero = 0; // Don't use memchr() to see if the character is a + or -. -- dcn if(begin != end) { char c = __N(*begin); if (c=='-') { ++begin; negative = true; error_value += signed_value; } else if (c=='+') { ++begin; } } // Code to remove whitespace removed as non-standard conforming. const ios_base::fmtflags radflag = io.flags() & ios_base::basefield; if (radflag == ios_base::dec) radix = 10; else if (radflag == ios_base::hex) radix = 16; else if (radflag == ios_base::oct) radix = 8; else radix = 0; if (begin != end && straits_type::eq (__N(*begin), '0')) { ++begin; char c = __N(*begin); if (begin != end && (radix == 16|| radix==0) && ( straits_type::eq(c, 'x') || straits_type::eq(c, 'X'))) { ++begin; radix = 16; } else { // Fixed by ADR. Modena's original routine cannot scan a plain // "0" string correctly because it reads the 0, figures out the // radix, and then forgets to put the '0' in the buffer! leading_zero = 1; if(radix == 0) radix = 8; } } register unsigned long value = 0; if (radix==10) { static char buffer[200]; buffer[0] = 0; for (;begin != end; ++begin) { char c = __N(*begin); if ('0' <= c && c <= '9') { register int digit = c - '0'; buffer[digits_seen] = digit; ++digits_seen; value = value * 10 + digit; } else if (Size && c==thou_sep) seps[num_seps++] = digits_seen; else break; } if (digits_seen > 9) { unsigned long new_value = 0; unsigned long old_value = 0; int i = 0; for (; i= old_value; ++i) { old_value = new_value; new_value = new_value * 10 + buffer[i]; } if (i!=digits_seen || new_value < old_value) { radix = -1; // errno = ERANGE; return error_value; } } } else if (radix == 8) { unsigned long mask = ~(~0UL >> 3); for (;begin != end; ++begin) { char c = __N(*begin); if ('0' <= c && c <= '7') { if ((value & mask) != 0) { radix = -1; // errno = ERANGE; return error_value; } unsigned long digit = c - '0'; value = (value << 3) | digit; ++digits_seen; } else if (Size && c==thou_sep) seps[num_seps++] = digits_seen; else break; } } else if (radix == 16) { unsigned long mask = ~(~0UL >> 4); for (;begin != end; ++begin) { char c = __N(*begin); unsigned long digit; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': digit = c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': digit = c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': digit = c - 'A' + 10; break; default: if (Size && c==thou_sep) { seps[num_seps++] = digits_seen; continue; } else goto seen_all; } if ((value & mask) != 0) { // Catch overflow of local storage. radix = -1; // errno = ERANGE; return error_value; } value = (value << 4) | digit; ++digits_seen; } } seen_all: if (value & ~effective_bits) { // Catch overflow based on output size. radix = -1; // errno = ERANGE; value = error_value; } else { unsigned long sign_mask = (effective_bits>>1) + 1; if (value & sign_mask) { if (negative && value == sign_mask) ; // that's ok. else if (negative || signed_value) { radix = -1; // errno = ERANGE; value = error_value; } } else if (negative) value = (-value) & effective_bits; // Negate and trucate to the effective width. } if (!(digits_seen+leading_zero)) radix = -1; if (num_seps) { size_t count = 0; const int MAX_CHAR = numeric_limits::max (); do { if (grp[count] == MAX_CHAR) radix = -1; else { digits_seen -= (grp[count] & 0xF); if (digits_seen != seps[--num_seps]) radix = -1; else if ((count+1) < Size) ++count; } } while (num_seps && radix != -1); if (grp[count] != MAX_CHAR && digits_seen > (grp[count] & 0xF)) radix = -1; } return value; } #ifdef __KAI_LONG_LONG template unsigned __long_long num_get:: kai_scan_long_long_type(iter_type &begin, iter_type &end, ios_base& io, int &radix, int signed_value, unsigned __long_long effective_bits) { typedef char_traits straits_type; const locale& loc = io.getloc (); const numpunct& punct = use_facet >(loc); const string grp(punct.grouping()); const char thou_sep(punct.thousands_sep()); unsigned long error_value = signed_value ? (effective_bits>>1) : effective_bits; int seps [40]; int num_seps = 0; int digits_seen = 0; const int Size = grp.size(); bool negative = false; int leading_zero = 0; // Don't use memchr() to see if the character is a + or -. -- dcn if(begin != end) { char c = __N(*begin); if (c=='-') { ++begin; negative = true; error_value += signed_value ? 1:0; } else if (c=='+') { ++begin; } } // Code to skip whitespace removed as non-standard conforming. const ios_base::fmtflags radflag = io.flags() & ios_base::basefield; if (radflag == ios_base::dec) radix = 10; else if (radflag == ios_base::hex) radix = 16; else if (radflag == ios_base::oct) radix = 8; else radix = 0; if (begin != end && straits_type::eq (__N(*begin), '0')) { ++begin; char c = __N(*begin); if (begin != end && (radix == 16|| radix==0) && ( straits_type::eq(c, 'x') || straits_type::eq(c, 'X'))) { ++begin; radix = 16; } else { // Fixed by ADR. Modena's original routine cannot scan a plain // "0" string correctly because it reads the 0, figures out the // radix, and then forgets to put the '0' in the buffer! leading_zero = 1; if(radix == 0) radix = 8; } } register unsigned __long_long value = 0; if (radix==10) { static char buffer[200]; buffer[0] = 0; for (;begin != end; ++begin) { char c = __N(*begin); if ('0' <= c && c <= '9') { register int digit = c - '0'; buffer[digits_seen] = digit; ++digits_seen; value = value * 10 + digit; } else if (Size && c==thou_sep) seps[num_seps++] = digits_seen; else break; } if (digits_seen > 9) { unsigned __long_long new_value = 0; unsigned __long_long old_value = 0; int i = 0; for (; i= old_value; ++i) { old_value = new_value; new_value = new_value * 10 + buffer[i]; } if (i!=digits_seen || new_value < old_value) { radix = -1; // errno = ERANGE; return error_value; } } } else if (radix == 8) { unsigned __long_long mask = ~(~0UL >> 3); for (;begin != end; ++begin) { char c = __N(*begin); if ('0' <= c && c <= '7') { if ((value & mask) != 0) { radix = -1; // errno = ERANGE; return error_value; } unsigned long digit = c - '0'; value = (value << 3) | digit; ++digits_seen; } else if (Size && c==thou_sep) seps[num_seps++] = digits_seen; else break; } } else if (radix == 16) { unsigned __long_long mask = ~(~0UL >> 4); for (;begin != end; ++begin) { char c = __N(*begin); unsigned long digit; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': digit = c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': digit = c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': digit = c - 'A' + 10; break; default: if (Size && c==thou_sep) { seps[num_seps++] = digits_seen; continue; } else goto seen_all; } if ((value & mask) != 0) { // Catch overflow of local storage. radix = -1; // errno = ERANGE; return error_value; } value = (value << 4) | digit; ++digits_seen; } } seen_all: if (value & ~effective_bits) { // Catch overflow based on output size. radix = -1; // errno = ERANGE; value = error_value; } else { unsigned __long_long sign_mask = (effective_bits>>1) + 1; if (value & sign_mask) { if (negative && value == sign_mask) ; // that's ok. else if (negative || signed_value) { radix = -1; // errno = ERANGE; value = error_value; } } else if (negative) value = (-value) & effective_bits; // Negate and trucate to the effective width. } if (!(digits_seen+leading_zero)) radix = -1; if (num_seps) { size_t count = 0; const int MAX_CHAR = numeric_limits::max (); do { if (grp[count] == MAX_CHAR) radix = -1; else { digits_seen -= (grp[count] & 0xF); if (digits_seen != seps[--num_seps]) radix = -1; else if ((count+1) < Size) ++count; } } while (num_seps && radix != -1); if (grp[count] != MAX_CHAR && digits_seen > (grp[count] & 0xF)) radix = -1; } return value; } #endif /* __KAI_LONG_LONG */ template bool num_get::scan_float_type (iter_type& begin, iter_type& end, ios_base& io, char* buf) { typedef char_traits straits_type; const locale& loc = io.getloc (); const numpunct& punct = use_facet >(loc); const string grp = punct.grouping(); const char thou_sep = punct.thousands_sep(); bool flag = false; int seps [20]; int num_seps = 0; int digits_seen = 0; const int Size = grp.size(); char* cur = buf; if (begin != end && memchr ("-+", *cur = __N(*begin), 2)) ++cur, ++begin; // Modena 2.4 had here that skipped whitespace, which contradicts standard. // They took it out in 2.6. char ch = __N(*begin); while (begin != end) { if ('0' <= ch && ch <= '9') { flag = false; *cur = ch; ++cur; ++digits_seen; ch = __N(*++begin); } else if (Size && ch == thou_sep) { flag = true; seps[num_seps++] = digits_seen; ch = __N(*++begin); } else { break; } } if (flag) return false; flag = true; if (begin != end && straits_type::eq(*begin, punct.decimal_point())) { *cur = localeconv()->decimal_point[0]; ++cur; ch = __N(*++begin); while (begin != end && '0' <= ch && ch <= '9') { *cur = ch; ++cur; ch = __N(*++begin); flag = false; } } if (!digits_seen && flag) return false; flag = false; if (begin != end && (ch=='e' || ch=='E')) { flag = true; *cur = ch; ++cur; ch = __N(*++begin); if (begin != end && (ch=='-' || ch=='+')) { *cur = ch; ++cur; ch = __N(*++begin); } // Code to remove whitespace removed as non-standard conforming. while (begin != end && '0' <= ch && ch <= '9') { *cur = ch; ++cur; ch = __N(*++begin); flag = false; } } if (flag) return false; size_t count = 0; const int MAX_CHAR = numeric_limits::max(); if (num_seps) { do { if (grp[count] == MAX_CHAR) return false; else if ((digits_seen -= (grp[count] & 0xF)) != seps[--num_seps]) return false; else if ((count+1) < Size) ++count; } while (num_seps); if (digits_seen > (grp[count] & 0xF)) return false; } *cur = '\0'; return true; } template num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, float& units) const { char buf [200] = ""; float result = 0.0F; int scanned = 0; if (scan_float_type(begin, end, io, buf)) scanned = sscanf(buf, "%f", &result); if (begin == end) state |= ios_base::eofbit; if (scanned != 1) state |= ios_base::failbit; else units = result; return begin; } template num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, double& units) const { char buf [200] = ""; double result = 0.0F; int scanned = 0; if (scan_float_type(begin, end, io, buf)) scanned = sscanf(buf, "%lf", &result); if (begin == end) state |= ios_base::eofbit; if (scanned != 1) state |= ios_base::failbit; else units = result; return begin; } template num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, long double& units) const { char buf [200] = ""; long double result = 0.0F; int scanned = 0; char fmt[4] = "%Lf"; if (scan_float_type(begin, end, io, buf)) scanned = sscanf(buf, fmt, &result); if (begin == end) state |= ios_base::eofbit; if (scanned != 1) state |= ios_base::failbit; else units = result; return begin; } template num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, void*& units) const { char buf [200] = ""; int OldErr = errno; void* result = 0; char *cur = buf; for (; (begin != end) && (memchr("0123456789abcdefABCDEFxX", __N(*begin), 24)); ++begin, ++cur) *cur = __N(*begin); *cur = charT (0); if (begin == end) state |= ios_base::eofbit; if (!sscanf(buf, "%p", &result) || (errno == ERANGE)) state |= ios_base::failbit; else units = result; errno = OldErr; return begin; } #if __KAI_LONG_LONG template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, __long_long& units) const { int radix; __long_long result = kai_scan_long_long_type(begin, end, io, radix, 1, (unsigned __long_long)-1); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = result; return begin; } template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, unsigned __long_long& units) const { int radix; unsigned __long_long result = kai_scan_long_long_type(begin, end, io, radix, 0, (unsigned __long_long)-1); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = result; return begin; } #endif /* __KAI_LONG_LONG */ template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, long& units) const { // Simplified by KAI. int radix; long result = kai_scan_integral_type(begin, end, io, radix, 1, ULONG_MAX); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = result; return begin; } template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, unsigned long& units) const { // Simplified by KAI. int radix; unsigned long result = kai_scan_integral_type(begin, end, io, radix, 0, ULONG_MAX); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = result; return begin; } template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, unsigned short& units) const { // Simplified by KAI. int radix; unsigned long result = kai_scan_integral_type(begin, end, io, radix, 0, USHRT_MAX); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = (unsigned short)result; return begin; } template inline num_get::iter_type num_get:: do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, unsigned int& units) const { // Simplified by KAI. int radix; unsigned long result = kai_scan_integral_type(begin, end, io, radix, 0, UINT_MAX); if (begin == end) state |= ios_base::eofbit; if (radix == -1) state |= ios_base::failbit; units = (unsigned int)result; return begin; } template num_get::iter_type num_get::do_get(iter_type begin, iter_type end, ios_base& io, iostate& state, bool& units) const { // Major changes by KAI to make it work correctly. if (io.flags() & ios_base::boolalpha) { typedef basic_string string_type; const locale& loc = io.getloc (); // Modena code to remove whitespace removed as non-standard conforming. if (begin==end) { state |= ios_base::eofbit; return begin; } // Assume that true_name & false_name are non-empty const numpunct& punct = use_facet >(loc); string_type tname = punct.truename(); string_type fname = punct.falsename(); int lengths[2]; lengths[0] = fname.size(); lengths[1] = tname.size(); const charT * names[2]; names[0] = fname.data(); names[1] = tname.data(); int bool_pos = 0; while (begin != end) { for (int i=0; i<2; ++i) { if (bool_pos < lengths[i] && !char_traits::eq(*begin, names[i][bool_pos])) { lengths[i] = 0; if( lengths[1-i]==0 ) goto fail; } else if (bool_pos+1 == lengths[i]) { units = i; #if 0 // Section 22.2.2.1.2p16 is annoyingly ambiguous about whether the following // action is incorrect. ADR took it out based on a strict interpretation. if( begin+1 == end ) state |= ios_base::eofbit; #endif /* 0 */ return begin; } } ++bool_pos; ++begin; } state |= ios_base::eofbit; } else { // Section 22.2.2.1.2p14 long tmp; begin = do_get( begin, end, io, state, tmp ); if( state&ios_base::failbit ) return begin; if( (unsigned long)tmp>=2UL ) goto fail; units = tmp; } return begin; fail: state |= ios_base::failbit; return begin; } #undef __N // ************** COLLATE FACETS *********************** template class collate : public locale::facet { public: typedef charT char_type; typedef basic_string string_type; explicit collate(size_t refs = 0) : locale::facet(refs) { } int compare(const char_type* low1, const char_type* high1, const char_type* low2, const char_type* high2) const { return do_compare(low1, high1, low2, high2); } string_type transform(const char_type* low, const char_type* high) const { return do_transform(low, high); } long hash(const char_type* low, const char_type* high) const { return do_hash(low, high); } static locale::id id; protected: ~collate () { } virtual int do_compare(const char_type* low1, const char_type* high1, const char_type* low2, const char_type* high2) const; virtual string_type do_transform(const char_type* low, const char_type* high) const; virtual long do_hash(const char_type* low, const char_type* high) const; }; template locale::id collate::id; template class collate_byname : public collate { public: explicit collate_byname(const char * name_, size_t refs = 0) : collate(refs), name(name_) { } protected: ~collate_byname() { } string name; }; // Specialization for char template<> class collate : public locale::facet { // friend class locale::imp; public: typedef char char_type; typedef string string_type; protected: virtual int do_compare(const char* low1, const char* high1, const char* low2, const char* high2) const; virtual string_type do_transform(const char* low, const char* high) const; virtual long do_hash(const char* low, const char* high) const; public: int compare(const char* low1, const char* high1, const char* low2, const char* high2) const { return do_compare(low1, high1, low2, high2); } string_type transform(const char* low, const char* high) const { return do_transform(low, high); } long hash(const char* low, const char* high) const { return do_hash(low, high); } static locale::id id; explicit collate(size_t refs = 0) : locale::facet(refs) { } protected: ~collate() { } }; #if KAI_WCHAR_T template<> class collate : public locale::facet { // friend class locale::imp; public: typedef wchar_t char_type; typedef basic_string, allocator > string_type; protected: virtual int do_compare(const char_type* low1, const char_type* high1, const char_type* low2, const char_type* high2) const; virtual string_type do_transform(const char_type* low, const char_type* high) const; virtual long do_hash(const char_type* low, const char_type* high) const; public: int compare(const char_type* low1, const char_type* high1, const char_type* low2, const char_type* high2) const { return do_compare(low1, high1, low2, high2); } string_type transform(const char_type* low, const char_type* high) const { return do_transform(low, high); } long hash(const char_type* low, const char_type* high) const { return do_hash(low, high); } static locale::id id; explicit collate(size_t refs = 0) : locale::facet(refs) { } protected: ~collate () { } }; #endif /* KAI_WCHAR_T */ //************** Time Category *********************** class time_base { public: enum dateorder { no_order, dmy, mdy, ymd, ydm }; enum t_conv_spec { a, A, b, B, c, d, H, I, j, m, M, p, S, U, w, W, x, X, y, Y, __END }; }; } // namespace std namespace __kai { // this class is not specified in the draft : written for // implementation purposes only // need to write specialization for wchar_t using namespace std; template class timepunct : public time_base { public: static const int t_conv_spec_width[time_base::__END+1]; typedef charT char_type; typedef basic_string, allocator > string_type; explicit timepunct(const char* loc_name = ""); virtual string_type get_week_day(const locale& loc, charT fmt, int wday) const { return (isupper(fmt, loc) ? week_days[wday+7] : week_days[wday]); } //virtual string_type const string_type& get_month_name(const locale& loc, char fmt, int mnth) const { return (isupper(fmt, loc) ? mnth_name[mnth+12] : mnth_name[mnth]); } virtual string_type get_ampm_string (int hrs) const { return (12 - hrs > 0) ? am_string : pm_string; } // strftime like function virtual string_type print_format(const locale& loc, char fmt, const tm* tm_) const; virtual string_type* get_week_day_list() const { return (string_type*)week_days; } virtual string_type* get_month_name_list() const { return (string_type*)mnth_name; } virtual int get_spec_conv_width(charT spec) { switch (spec) { case 'a': return t_conv_spec_width[time_base::a]; case 'A': return t_conv_spec_width[time_base::A]; case 'b': return t_conv_spec_width[time_base::b]; case 'B': return t_conv_spec_width[time_base::B]; case 'c': return t_conv_spec_width[time_base::c]; case 'd': return t_conv_spec_width[time_base::d]; case 'H': return t_conv_spec_width[time_base::H]; case 'I': return t_conv_spec_width[time_base::I]; case 'j': return t_conv_spec_width[time_base::j]; case 'm': return t_conv_spec_width[time_base::m]; case 'M': return t_conv_spec_width[time_base::M]; case 'p': return t_conv_spec_width[time_base::p]; case 'S': return t_conv_spec_width[time_base::S]; case 'U': return t_conv_spec_width[time_base::U]; case 'w': return t_conv_spec_width[time_base::w]; case 'W': return t_conv_spec_width[time_base::W]; case 'x': return t_conv_spec_width[time_base::x]; case 'X': return t_conv_spec_width[time_base::X]; case 'y': return t_conv_spec_width[time_base::y]; case 'Y': return t_conv_spec_width[time_base::Y]; default: return t_conv_spec_width[time_base::__END]; } } // eqvt to "%c" strftime virtual string_type get_date_time_format() const { return __kai::convert_locale_string( "%a %b %d %H:%M:%S %Y" ); } // eqvt to "%x" strftime virtual string_type get_date_format() const { return __kai::convert_locale_string( "%m/%d/%y" ); } // eqvt to "%X" strftime virtual string_type get_time_format() const { return __kai::convert_locale_string( "%H:%M:%S" ); } protected: string loc_name; string_type week_days[14]; // week days names string_type mnth_name[24]; // month names string_type am_string; // am_string string_type pm_string; // pm_string }; template const int timepunct::t_conv_spec_width[time_base::__END+1] = { 3, -1, 3, -1, -1, 2, 2, 2, 3, 2, 2, -1, 2, 2, 1, 2, -1, -1, 2, 4, 0 }; // Z='Z' ; Time Zones not supported yet template timepunct::timepunct (const char* loc_name_) : loc_name (loc_name_) { const char* old_loc_name = setlocale(LC_ALL, 0); if (setlocale(LC_TIME, loc_name_) != 0) { tm tmb; tmb.tm_sec = 30; tmb.tm_min = 30; tmb.tm_hour = 10; tmb.tm_mday = 1; tmb.tm_mon = 8; tmb.tm_year = 96; tmb.tm_wday = 0; tmb.tm_yday = -1; tmb.tm_isdst = -1; #if (defined(__linux)&&!defined(__ICC)) // KAI change - need to clear extra fields added by Linux, otherwise strftime crashes. #ifdef __USE_BSD tmb.tm_gmtoff = 0; tmb.tm_zone = 0; #else tmb.__tm_gmtoff = 0; tmb.__tm_zone = 0; #endif #endif /* __linux */ char fmt[3]; static const int MAXBUFF = 512; char buff[MAXBUFF]; unsigned int MB = MAXBUFF; fmt[0] = '%'; fmt[1] = 'c' ; fmt[2] = 0; // get the week days names for (int days = 0; days < 7; ++days) { tmb.tm_mday = days+1; tmb.tm_wday = days; // just to be sure fmt[1] = 'a'; strftime(buff, MB, fmt, &tmb); week_days[days] = __kai::convert_locale_string(buff); fmt[1] = 'A'; strftime(buff, MB, fmt, &tmb); week_days[days+7] = __kai::convert_locale_string(buff); } // get the month names for (int mths = 0; mths < 12; ++mths) { tmb.tm_mon = mths; fmt[1] = 'b'; strftime(buff, MB, fmt, &tmb); mnth_name[mths] = __kai::convert_locale_string(buff); fmt[1] = 'B'; strftime(buff, MB, fmt, &tmb); mnth_name[mths+12] = __kai::convert_locale_string(buff); } // get the am / pm strings fmt[1] = 'p'; strftime(buff, MB, fmt, &tmb); am_string = __kai::convert_locale_string(buff); tmb.tm_hour = 22; fmt[1] = 'p'; strftime(buff, MB, fmt, &tmb); pm_string = __kai::convert_locale_string(buff); } else runtime_error::__throw("Invalid locale name\n"); setlocale(LC_ALL, old_loc_name); } template timepunct::string_type timepunct::print_format(const locale& loc, char fmt, const tm* tm_) const { char fmt_str[10]; fmt_str[0] = '%'; static const int MAXBUFF = 512; char buff[MAXBUFF]; // Initialize buff[0] to zero. If a non-trivial sprintf is done to it, then buff[0] // will be non-zero, and we'll known to append it after the switch statement. buff[0] = 0; // unsigned int MB = MAXBUFF; fmt_str[1] = '.'; fmt_str[2] = '2'; fmt_str[3] = 'd'; fmt_str[4] = 0; string_type ret; switch (fmt) { case 'a': if (tm_->tm_wday >= 0 && tm_->tm_wday < 7) ret.append(week_days[tm_->tm_wday]); break; case 'A': if (tm_->tm_wday >= 0 && tm_->tm_wday < 7) ret.append(week_days[tm_->tm_wday + 7]); break; case 'b': if (tm_->tm_mon >= 0 && tm_->tm_mon < 12) ret.append(mnth_name[tm_->tm_mon]); break; case 'B': if (tm_->tm_mon >= 0 && tm_->tm_mon < 12) ret.append(mnth_name[tm_->tm_mon + 12]); break; case 'p': if (tm_->tm_hour >= 0 && tm_->tm_hour < 24) ret.append((tm_->tm_hour < 12)? am_string : pm_string); break; case 'd': if (tm_->tm_mday > 0 && tm_->tm_mday <= 31) { sprintf(buff, fmt_str, tm_->tm_mday); } break; case 'H': if (tm_->tm_hour >= 0 && tm_->tm_hour < 24) { sprintf(buff, fmt_str, tm_->tm_hour); } break; case 'I': { int hr; // [00, 23] to [01, 12] if (tm_->tm_hour >= 0 && tm_->tm_hour < 24) { if (tm_->tm_hour == 0) hr = 12; else if (tm_->tm_hour > 12) hr = tm_->tm_hour - 12; sprintf(buff, fmt_str, hr); } break; } case 'm': if (tm_->tm_mon >= 0 && tm_->tm_mon < 12) { sprintf(buff, fmt_str, tm_->tm_mon+1); } break; case 'M': if (tm_->tm_min >= 0 && tm_->tm_min < 60) { sprintf(buff, fmt_str, tm_->tm_min); } break; case 'S': if (tm_->tm_sec >= 0 && tm_->tm_sec < 60) { sprintf(buff, fmt_str, tm_->tm_sec); } break; case 'U': { if (tm_->tm_wday >= 0 && tm_->tm_wday < 7) if (tm_->tm_yday >= 0 && tm_->tm_yday <= 365) { int U_dat = (tm_->tm_yday - tm_->tm_wday + 7)/7; sprintf(buff, fmt_str, U_dat); } break; } case 'W': { if (tm_->tm_wday >= 0 && tm_->tm_wday < 7) if (tm_->tm_yday >= 0 && tm_->tm_yday <= 365) { int to_arr [7] = { 6, 0, 1, 2, 3, 4, 5 }; int W_dat = (tm_->tm_yday - to_arr[tm_->tm_wday] + 7)/7; sprintf(buff, fmt_str, W_dat); } break; } case 'y': sprintf(buff, fmt_str, tm_->tm_year); break; case 'w': if (tm_->tm_wday >= 0 && tm_->tm_wday < 7) { fmt_str[2] = '1'; sprintf(buff, fmt_str, tm_->tm_wday); } break; case 'Y': fmt_str[2] = '4'; sprintf(buff, fmt_str, 1900+tm_->tm_year); break; case 'j': if (tm_->tm_yday >= 0 && tm_->tm_yday <= 365) { fmt_str[2] = '3'; sprintf(buff, fmt_str, tm_->tm_yday+1); } break; default: if (fmt == '%') ret.append(1, fmt); break; } if( buff[0] ) { // sprintf wrote something to buff ret = __kai::convert_locale_string(buff); } return ret; } inline char* build_fmt(const ios_base& io, char* buf, int idx) { // Build format string suitable for printf/scanf. // // Size of buf is at least 16. // // idx - 1 ==> long // idx - 2 ==> unsigned long // idx - 3 ==> double // idx - 4 ==> long double typedef basic_string string_type; ios_base::fmtflags flags = io.flags(); char* cur = buf; *cur++ = '%'; if (flags & ios_base::showpos) { *cur++ = '+'; } int radix = 10; radix = (flags & ios_base::oct) ? 8 : (flags & ios_base::hex) ? 16 : 10; // handle showbase and showpoint // for integral, # goes for showbase (only for oct and hex) // for float , # goes for showpoint if (((idx < 3) && (radix != 10) && (flags & ios_base::showbase)) || ((idx > 2) && (flags & ios_base::showpoint))) { *cur++ = '#'; } if (idx > 2) { // for floating point types only char tmp[4]; *cur++ = '.'; tmp[0] = '%'; tmp[1] = 'l'; tmp[2] = 'u'; tmp[3] = char(); sprintf(cur, tmp, io.precision()); cur += string_type::traits_type::length(cur); } if (idx < 3) { // integral quantities *cur++ = 'l'; switch (radix) { case 8: *cur++ = 'o'; break; case 16: if (flags & ios_base::uppercase) *cur++ = 'X'; else *cur++ = 'x'; break; case 10: default: if (idx == 1) *cur++ = 'd'; else // unsigned long *cur++ = 'u'; break; } } else { // for floating point output. // ADR corrected Modena's prolix (and wrong) logic for when // to add the 'L'. if( idx == 4 ) { // long double *cur++ = 'L'; } switch (flags & ios_base::floatfield) { case ios_base::scientific: *cur++ = ((flags & ios_base::uppercase) ? 'E' : 'e'); break; case ios_base::fixed: *cur++ = 'f'; break; default: *cur++ = ((flags & ios_base::uppercase) ? 'G' : 'g'); break; } } *cur = char(); return cur; } template inline basic_string insert_thsep(basic_string str, const string& grp, charT sep, charT pt) { typedef basic_string string_type; typedef string_type::traits_type traits_type; // Search for localeconv()->decimal_pt string_type _decimal_point = __kai::convert_locale_string( localeconv()->decimal_point ); size_t pos = str.rfind(_decimal_point); if (pos != string_type::npos) str.replace(pos, 1, 1, pt); else pos = str.size(); if (!str.empty()) { int shift; int limit = 0; size_t count = 0; if (traits_type::eq(str[0], '0')) { ++limit; if ((str.size() >= 2) && (traits_type::eq(str[1], 'X') || traits_type::eq(str[1], 'x'))) { ++limit; } } else if ((traits_type::eq (str[0], '+') || traits_type::eq (str[0], '-'))) { ++limit; } while ((count < grp.size ()) && (grp[count] != numeric_limits::max())) { shift = grp[count] & 0xf; if (pos-limit <= shift) break; pos -= shift; str.insert(pos, 1, sep); count++; } if (count == grp.size() && count != 0) { while (pos-limit > shift) { pos -= shift; str.insert(pos, 1, sep); } } } return str; } } // namespace __kai namespace std { template > class time_get : public locale::facet, public time_base { typedef basic_string string_type; typedef ios_base::iostate iostate; public: typedef charT char_type; typedef InputIterator iter_type; explicit time_get(size_t refs = 0) : locale::facet(refs) { } dateorder date_order() const { return do_date_order(); } iter_type get_time(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const { return do_get_time(s, end, f, state, t); } iter_type get_date(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const { return do_get_date(s, end, f, state, t); } iter_type get_weekday(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const { return do_get_weekday(s, end, f, state, t); } iter_type get_monthname(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const { return do_get_monthname(s, end, f, state, t); } iter_type get_year(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const { return do_get_year(s, end, f, state, t); } static locale::id id; protected: ~time_get() { } explicit time_get(const char* name, size_t refs = 0) : locale::facet (refs), name_ (name) { } virtual dateorder do_date_order() const { return time_base::dmy; } virtual iter_type do_get_time(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const; virtual iter_type do_get_date(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const; virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const; virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const; virtual iter_type do_get_year(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t) const; virtual iter_type which_matches(iter_type s, iter_type end, ios_base& f, iostate& state, const string_type*, int, int&) const; virtual iter_type get_integral_data(iter_type s, iter_type end, ios_base& f, iostate& state, charT fmt, int&) const; virtual iter_type do_time_scanf(iter_type s, iter_type end, ios_base& f, iostate& state, tm* t, const char* pattern, const char* pat_end) const; string name_; // Plain string of char, not charT }; /* end class time_get */ template > class time_get_byname : public time_get { public: explicit time_get_byname(const char* name, size_t refs = 0) : time_get(name, refs) { } protected: ~time_get_byname(); }; template locale::id time_get::id; template time_get::iter_type time_get::do_get_time(iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t) const { __kai::timepunct tpunct; string time_list = tpunct.get_time_format(); return do_time_scanf(begin, end, io, state, t, time_list.c_str(), time_list.c_str() + time_list.size()); } template time_get::iter_type time_get::do_time_scanf (iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t, const char* pattern, const char* pat_end) const { __kai::timepunct tpunct; int val; const locale& loc = io.getloc(); const ctype& ctype_ = use_facet >(loc); while ((pattern != pat_end) && !state) { if (!string_type::traits_type::eq (*pattern, '%')) { if (!string_type::traits_type::eq (*begin, *pattern)) { state |= ios_base::failbit; return begin; } else { begin++; pattern++; } } else { char_type c; switch (c = *++pattern) { // Assuming the appropriate versions will be given // No checking is done to check that!! case 'a': case 'A': begin = get_weekday(begin, end, io, state, t); break; case 'b': case 'B': begin = get_monthname(begin, end, io, state, t); break; case 'd': begin = get_integral_data(begin, end, io, state, c, val); if (val < 1 || val > 31) state |= ios_base::failbit; else t->tm_mday = val; break; case 'H': begin = get_integral_data(begin, end, io, state, c, val); if (val < 0 || val > 23) state |= ios_base::failbit; else t->tm_hour = val; break; case 'I': { begin = get_integral_data(begin, end, io, state, c, val); if (val < 1 || val > 12) state |= ios_base::failbit; else t->tm_hour = val - 1; break; } case 'j': { begin = get_integral_data(begin, end, io, state, c, val); if (val < 0 || val > 365) state |= ios_base::failbit; else t->tm_yday = ++val; break; } case 'm': { begin = get_integral_data(begin, end, io, state, c, val); if (val <= 0 || val > 12) state |= ios_base::failbit; else t->tm_mon = --val; break; } case 'M': begin = get_integral_data(begin, end, io, state, c, val); if (val < 0 || val > 59) state |= ios_base::failbit; else t->tm_min = val; break; case 'p': case 'U': case 'W': // TODO: YET TO BE DONE break; case 'S': begin = get_integral_data(begin, end, io, state, c, val); if (val < 0 || val > 59) state |= ios_base::failbit; else t->tm_sec = val; break; case 'w': begin = get_integral_data(begin, end, io, state, c, val); if (val < 0 || val > 6) state |= ios_base::failbit; else t->tm_wday = val; break; case 'y': case 'Y': { begin = get_integral_data(begin, end, io, state, c, t->tm_year); if (t->tm_year > 1900) t->tm_year -= 1900; else if (t->tm_year < 0) state |= ios_base::failbit; break; } default: state |= ios_base::failbit; break; } /* end switch */ pattern++; } } /* end while */ return begin; } template inline time_get::iter_type time_get::do_get_date(iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t) const { __kai::timepunct tpunct; string date_list = tpunct.get_date_format(); const locale& loc = io.getloc(); return do_time_scanf(begin, end, io, state, t, date_list.c_str(), date_list.c_str() + date_list.size()); } template inline time_get::iter_type time_get::do_get_weekday(iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t) const { __kai::timepunct tpunct; int wday = 0; iter_type ret = which_matches(begin, end, io, state, tpunct.get_week_day_list(), 14, wday); if (wday != -1) t->tm_wday = (wday > 6) ? (wday - 7) : wday; else state |= ios_base::failbit; return ret; } template time_get::iter_type time_get::do_get_monthname(iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t) const { __kai::timepunct tpunct; int mnth = 0; iter_type ret = which_matches(begin, end, io, state, tpunct.get_month_name_list(), 24, mnth); if (mnth != -1) t->tm_mon =(mnth > 11) ? mnth - 12 : mnth; else state |= ios_base::failbit; return ret; } template time_get::iter_type time_get::get_integral_data(iter_type begin, iter_type end, ios_base& io, iostate& state, charT fmt, int& data) const { data = 0; __kai::timepunct tpunct; int width = tpunct.get_spec_conv_width(fmt); if (width < 0) return begin; const locale& loc = io.getloc(); const ctype& ctype_ = use_facet >(loc); if (io.flags() & ios_base::skipws) { while ((begin != end) && isspace(*begin, loc)) ++begin; } else if (isspace(*begin, loc)) { state |= ios_base::failbit; return begin; } while (begin != end && isdigit(*begin, loc) && width--) { data = data * 10 + (ctype_.narrow(*begin, 0) - '0'); begin++; } return begin; } template time_get::iter_type time_get:: do_get_year(iter_type begin, iter_type end, ios_base& io, iostate& state, tm* t) const { int year = 0; const locale& loc = io.getloc(); const ctype& ctype_ = use_facet >(loc); if (io.flags() & ios_base::skipws) { while ((begin != end) && isspace(*begin, loc)) ++begin; } else if (isspace(*begin, loc)) { state |= ios_base::failbit; return begin; } while (begin != end && isdigit(*begin, loc)) { year = year * 10 + (ctype_.narrow(*begin, 0) - '0'); begin++; } if (year && year < 100) t->tm_year = year; else if (year > 1900) t->tm_year = year - 1900; else state |= ios_base::failbit; return begin; } template time_get::iter_type time_get:: which_matches(iter_type begin, iter_type end, ios_base& io, iostate& state, const string_type* str_list, int list_size, int& matchPos) const { int strPos = 0; int startFrom = 0; string_type str; str.reserve(100); bool foundMatch = false; const locale& loc = io.getloc(); if (io.flags() & ios_base::skipws) { while ((begin != end) && isspace(*begin, loc)) ++begin; } else if (isspace(*begin, loc)) { state |= ios_base::failbit; return begin; } while (begin != end && !foundMatch && startFrom < list_size) { if (strPos < str_list[startFrom].size() && str_list[startFrom].compare(0, strPos, str, 0, strPos) == 0) { str.append(1, *begin); strPos++; begin++; if (str == str_list[startFrom] && ((startFrom < list_size/2 && begin == end) || (startFrom >=list_size/2) || isspace(*begin, loc))) foundMatch = true; } else startFrom++; } matchPos = (foundMatch ? startFrom : -1); return begin; } template > class time_put : public locale::facet { public: typedef charT char_type; typedef OutputIterator iter_type; typedef basic_string, allocator > string_type; explicit time_put(size_t refs = 0) : locale::facet(refs) { } iter_type put(iter_type s, ios_base&, char_type fill, const tm* tmb, const char_type* pattern, const char_type* pat_end) const; iter_type put(iter_type s, ios_base& io, char_type fill, const tm* tmb, char format, char modifier = 0) const { return do_put(s, io, fill, tmb, format, modifier); } static locale::id id; protected: virtual iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* tmb, char format, char modifier = 0) const; }; template > class time_put_byname : public time_put { public: typedef charT char_type; typedef OutputIterator iter_type; typedef basic_string, allocator > string_type; explicit time_put_byname(const char* name, size_t refs = 0) : time_put(name, refs) { } protected: ~time_put_byname() { } virtual iter_type do_put(iter_type s, ios_base& ss, tm* t, char format, char modifier) const { time_put::do_put(s, ss, t, format, modifier); } }; template locale::id time_put::id; template time_put::iter_type time_put::put(iter_type iter, ios_base& io, char_type fill, const tm* t, const char_type* pattern, const char_type* pat_end) const { const locale& loc = io.getloc(); const ctype& ctype_ = use_facet >(loc); __kai::timepunct tpunct; const char_type* cur = pattern; while (cur != pat_end) { // && *cur if (ctype_.narrow(*cur, 0) != '%') *iter++ = *cur++; else { char fmt = 0; if (pat_end != cur+1) fmt = ctype_.narrow(*++cur, 0); else return iter; if (fmt) { switch (fmt) { case 'c': { string_type date_time_fmt = tpunct.get_date_time_format(); const char_type* c_fmt_lst = date_time_fmt.c_str(); iter = put(iter, io, fill, t, c_fmt_lst, c_fmt_lst+string_type::traits_type:: length(c_fmt_lst)); break; } case 'x': { string_type date_fmt = tpunct.get_date_format(); const char_type* x_fmt_lst = date_fmt.c_str(); iter = put(iter, io, fill, t, x_fmt_lst, x_fmt_lst + string_type::traits_type:: length(x_fmt_lst)); break; } case 'X': { string_type time_fmt = tpunct.get_time_format(); const char_type* X_fmt_lst = time_fmt.c_str(); iter = put(iter, io, fill, t, X_fmt_lst, X_fmt_lst + string_type::traits_type:: length(X_fmt_lst)); break; } default: iter = do_put(iter, io, fill, t, fmt, 0); break; } cur++; } } } /* end while */ return iter; } template time_put::iter_type time_put::do_put(iter_type iter, ios_base& io, char_type fill, const tm* t, char format, char modifier) const { __kai::timepunct tpunct; switch (format) { case 'c': { string_type date_time_fmt = tpunct.get_date_time_format(); const char_type* c_fmt_lst = date_time_fmt.c_str(); iter = put(iter, io, fill, t, c_fmt_lst, c_fmt_lst + string_type::traits_type:: length(c_fmt_lst)); break; } case 'x': { string_type date_fmt = tpunct.get_date_format(); const char_type* x_fmt_lst = date_fmt.c_str(); iter = put(iter, io, fill, t, x_fmt_lst, x_fmt_lst + string_type::traits_type:: length(x_fmt_lst)); break; } case 'X': { string_type time_fmt = tpunct.get_time_format(); const char_type* X_fmt_lst = time_fmt.c_str(); iter = put(iter, io, fill, t, X_fmt_lst, X_fmt_lst + string_type::traits_type:: length(X_fmt_lst)); break; } default: string_type str = tpunct.print_format(io.getloc(), format, t); size_t cnt = 0; while (cnt < str.size()) { *iter++ = str[cnt]; cnt++; } } return iter; } //************** MONETARY FACETS *********************** class money_base { public: enum part { none='0', space=' ', symbol='?', sign='-', value='v' }; struct pattern { char field[4]; }; protected: // static pattern get_pat(); static pattern get_pat(int cs_precedes, int sep_by_space, int sign_posn, bool& paren); }; // end class money_base template class moneypunct : public locale::facet, public money_base { public: typedef charT char_type; typedef basic_string, allocator > string_type; static const bool intl = Intl; protected: virtual char_type do_decimal_point() const { return dec_pt; } virtual char_type do_thousands_sep() const { return thou_sep; } virtual string do_grouping() const { return grp; } virtual string_type do_curr_symbol() const { return curr_sym; } virtual string_type do_positive_sign() const { return pos_sign; } virtual string_type do_negative_sign() const { return neg_sign; } virtual int do_frac_digits() const { return frac_dig; } virtual money_base::pattern do_pos_format() const { return pos_fmt; } virtual money_base::pattern do_neg_format() const { return neg_fmt; } explicit moneypunct(const char* name, size_t refs = 0) : locale::facet (refs) { init (name); } ~moneypunct() { } public: char_type decimal_point() const { return do_decimal_point(); } char_type thousands_sep() const { return do_thousands_sep(); } string grouping() const { return do_grouping(); } string_type curr_symbol() const { return do_curr_symbol(); } string_type positive_sign() const { return do_positive_sign(); } string_type negative_sign() const { return do_negative_sign(); } int frac_digits() const { return do_frac_digits(); } money_base::pattern pos_format() const { return do_pos_format(); } money_base::pattern neg_format() const { return do_neg_format(); } explicit moneypunct(size_t refs = 0) : locale::facet(refs) { init(""); } static locale::id id; private: void init(const char* name); char_type dec_pt; char_type thou_sep; string_type curr_sym; string_type pos_sign; string_type neg_sign; string grp; int frac_dig; money_base::pattern pos_fmt; money_base::pattern neg_fmt; }; template void moneypunct::init(const char* name) { const char* old_name = setlocale(LC_ALL, 0); if (setlocale(LC_MONETARY, name) != 0) { struct lconv* lptr = localeconv(); curr_sym = __kai::convert_locale_string( intl ? lptr->int_curr_symbol : lptr->currency_symbol ); frac_dig = intl ? lptr->int_frac_digits : lptr->frac_digits; dec_pt = lptr->mon_decimal_point[0]; thou_sep = lptr->mon_thousands_sep[0]; pos_sign = __kai::convert_locale_string( lptr->positive_sign ); neg_sign = __kai::convert_locale_string( lptr->negative_sign ); grp = lptr->mon_grouping; bool paren; // Modena had some real silly code here. It masked off the high bits. // But, in the case of the sign position, it did not mask off enough // bits. The code also ignored the case where all the bits were set to // Indicate that the value was not available. The code now picks a // default value in the case where too many bits are available. The // values I have picked should return the pattern { symbol, sign, none, value } // as required by the C++ Standard (see 22.2.6.3.2 [lib.locale.moneypunct.virtuals]) // If intl, then the format is fixed. -- dcn if (intl) { pos_fmt.field[0] = symbol; pos_fmt.field[1] = sign; pos_fmt.field[2] = none; pos_fmt.field[3] = value; neg_fmt = pos_fmt; } else { int csymbol_preceeds = (lptr->p_cs_precedes & ~1) ? 1 : lptr->p_cs_precedes; int sep_by_space = (lptr->p_sep_by_space & ~1) ? 0 : lptr->p_sep_by_space; int sign_posn = (lptr->p_sign_posn & ~7) ? 4 : lptr->p_sign_posn; pos_fmt = money_base::get_pat(csymbol_preceeds, sep_by_space, sign_posn, paren); if (paren) { pos_sign.append(1, (char_type)'('); pos_sign.append(1, (char_type)')'); } csymbol_preceeds = (lptr->n_cs_precedes & ~1) ? 1 : lptr->n_cs_precedes; sep_by_space = (lptr->n_sep_by_space & ~1) ? 0 : lptr->n_sep_by_space; sign_posn = (lptr->n_sign_posn & ~7) ? 4 : lptr->n_sign_posn; neg_fmt = money_base::get_pat(csymbol_preceeds, sep_by_space, sign_posn, paren); if (paren) { neg_sign.append(1, (char_type)'('); neg_sign.append(1, (char_type)')'); } } } else runtime_error::__throw("Invalid locale name\n"); setlocale (LC_ALL, old_name); } template const bool moneypunct::intl; template locale::id moneypunct::id; template class moneypunct_byname : public moneypunct { // friend class locale::imp; public: typedef charT char_type; typedef basic_string, allocator > string_type; explicit moneypunct_byname (const char* name, size_t refs = 0) : moneypunct (name, refs) { } protected: ~moneypunct_byname() { } }; template > class money_put : public locale::facet { // friend class locale::imp; public: typedef charT char_type; typedef OutputIterator iter_type; typedef basic_string, allocator > string_type; protected: virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, long double units) const; virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, const string_type& digits) const; public: iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, long double& units) const { return do_put(s, intl, f, fill, units); } iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, string_type& digits) const { return do_put(s, intl, f, fill, digits); } static locale::id id; explicit money_put(size_t refs = 0) : locale::facet(refs) { } protected: ~money_put() { } }; template locale::id money_put::id; template > class money_get : public locale::facet { // friend class locale::imp; public: typedef charT char_type; typedef InputIterator iter_type; typedef basic_string, allocator > string_type; typedef ios_base::iostate iostate; protected: virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, iostate& state, long double& units) const; virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, iostate& state, string_type& digits) const; public: iter_type get(iter_type s, iter_type e, bool intl, ios_base& f, iostate& state, long double& units) const { return do_get(s, e, intl, f, state, units); } iter_type get(iter_type s, iter_type e, bool intl, ios_base& f, iostate& state, string_type& digits) const { return do_get(s, e, intl, f, state, digits); } static locale::id id; explicit money_get(size_t refs = 0) : locale::facet(refs) { } protected: ~money_get() { } private: static iter_type extract_value (iter_type begin, iter_type end, bool, ios_base& io, charT * buf, int& charTread); }; template locale::id money_get::id; template money_get::iter_type money_get:: extract_value (iter_type begin, iter_type end, bool international, ios_base& io, charT * buf, int& charTread) { typedef string_type::traits_type straits_type; const locale& loc = io.getloc(); string grp; char_type dec_pt; char_type thou_sep; int frac_dig; if (international) { const moneypunct& punctT = use_facet >(loc); grp = punctT.grouping(); dec_pt = punctT.decimal_point(); thou_sep = punctT.thousands_sep(); frac_dig = punctT.frac_digits(); } else { const moneypunct& punctF = use_facet >(loc); grp = punctF.grouping(); dec_pt = punctF.decimal_point(); thou_sep = punctF.thousands_sep(); frac_dig = punctF.frac_digits(); } charT * cur = buf; *cur = charT(); int Nfrac_dig = 0; const char * pgrp = grp.c_str(); if( pgrp <= '\0' || grp.c_str()==pgrp==CHAR_MAX ) { // 22.2.3.1.2 says unlimited size of group. while (begin != end && isdigit(*begin, loc)) *cur++ = *begin++; } else { // Have grouping to check. string seps; char digits_in_group = 0; for (; begin != end; ++begin) { if (isdigit(*begin, loc)) { *cur++ = *begin; if( digits_in_groupseps_begin ) { --pseps; if( *pgrp<=0 || *pgrp==CHAR_MAX ) { // Group can be any size. } else if( pseps==seps_begin ) { if( *pgrp<*pseps ) goto error; } else { if( *pgrp!=*pseps ) goto error; } if( pgrp < pgrp_end ) ++pgrp; } } } if (begin != end && straits_type::eq(*begin, dec_pt)) { while (++begin != end && isdigit(*begin, loc)) { if (Nfrac_dig >= frac_dig) goto error; *cur++ = *begin; ++Nfrac_dig; } } if (cur == buf) goto error; for (; Nfrac_dig < frac_dig; ++Nfrac_dig) *cur++ = '0'; *cur = charT(); charTread = cur - buf; return begin; error: charTread = 0; return begin; } template money_get::iter_type money_get:: do_get(iter_type begin, iter_type end, bool intl, ios_base& io, iostate& state, long double& units) const { typedef string_type::traits_type straits_type; string_type str; char buffer[200]; begin = do_get(begin, end, intl, io, state, str); __kai::convert_numeric_string( buffer, str ); long double result; char fmt[4] = "%Lf"; int scanned = sscanf(buffer, fmt, &result); if (scanned <= 0) state |= ios_base::failbit; else units = result; return begin; } template money_get::iter_type money_get:: do_get(iter_type begin, iter_type end, bool international, ios_base& io, iostate& state, string_type& digits) const { typedef string_type::traits_type straits_type; const locale& loc = io.getloc(); string_type curr_sym; string_type pos_sign; string_type neg_sign; money_base::pattern _pattern; if (international) { const moneypunct& punctT = use_facet >(loc); curr_sym = punctT.curr_symbol(); neg_sign = punctT.negative_sign(); pos_sign = punctT.positive_sign(); _pattern = punctT.neg_format(); } else { const moneypunct& punctF = use_facet >(loc); curr_sym = punctF.curr_symbol(); neg_sign = punctF.negative_sign(); pos_sign = punctF.positive_sign(); _pattern = punctF.neg_format(); } string_type sign; charT buffer[200]; bool isNeg = false; bool paren = false; bool end_parsing = false; // eat the leading white spaces // if (io.flags() & ios_base::skipws) while ((begin != end) && isspace(*begin, loc)) ++begin; for (int index = 0; !end_parsing && index < 4; ++index) { switch (_pattern.field[index]) { case money_base::symbol: { if (io.flags() & ios_base::showbase) ; else if((index == 3 && !paren) || begin == end || !straits_type::eq(*begin, curr_sym[0])) curr_sym.erase(); int sym_pos = 0; int sym_sz = curr_sym.size(); for (; begin!=end && sym_pos 0 && straits_type::eq(*begin, pos_sign[0])) { ++begin; sign = pos_sign; isNeg = false; if (pos_sign.size() > 1) paren = true; } else if (neg_sign.size() > 0 && straits_type::eq(*begin, neg_sign[0])) { ++begin; sign = neg_sign; isNeg = true; if (neg_sign.size() > 1) paren = true; } else if (pos_sign.size() == 0 && neg_sign.size() == 0) { if (straits_type::eq(*begin, '+') || straits_type::eq(*begin, '-')) ++begin; isNeg = false; } else if (pos_sign.size() == 0) { if (straits_type::eq(*begin, '+')) ++begin; isNeg = false; } else if (neg_sign.size() == 0) { if (straits_type::eq(*begin, '-')) ++begin; isNeg = true; } else end_parsing = true; if (sign.size() == 1) sign.erase(); break; } case money_base::value: { int charTread = 0; begin = extract_value(begin, end, international, io, buffer, charTread); if (!charTread) end_parsing = true; break; } case money_base::space: { if (straits_type::eq(*begin, ' ') == 0) { end_parsing = true; break; } while (begin != end && straits_type::eq(*begin, ' ')) ++begin; break; } case money_base::none: { if (index == 3) break; while (begin != end && straits_type::eq(*begin, ' ')) ++begin; break; } } //end switch } // end for if (!end_parsing && sign.size() > 0) { int signPos = 1; while (begin != end && signPos < sign.size() && straits_type::eq(*begin, sign[signPos])) { ++signPos; ++begin; } if (signPos != sign.size()) end_parsing = true; } if (end_parsing) { state |= ios_base::failbit; return begin; } digits = buffer; if (isNeg) digits.insert((string_type::size_type)0, 1, '-'); return begin; } template money_put::iter_type money_put:: do_put(iter_type iter, bool intl, ios_base& io, char_type fill, long double units) const { const locale& loc = io.getloc(); const moneypunct& punctT = use_facet >(loc); const moneypunct& punctF = use_facet >(loc); string_type curr_sym; string_type pos_sign; string_type neg_sign; money_base::pattern neg_pat; money_base::pattern pos_pat; char_type dec_pt; char_type thou_sep; size_t frac_dig; string grp; // Must be string, not string_type. if (intl) { curr_sym = punctT.curr_symbol(); neg_pat = punctT.neg_format(); pos_pat = punctT.pos_format(); neg_sign = punctT.negative_sign(); pos_sign = punctT.positive_sign(); dec_pt = punctT.decimal_point(); thou_sep = punctT.thousands_sep(); frac_dig = punctT.frac_digits(); grp = punctT.grouping(); } else { curr_sym = punctF.curr_symbol(); neg_pat = punctF.neg_format(); pos_pat = punctF.pos_format(); neg_sign = punctF.negative_sign(); pos_sign = punctF.positive_sign(); dec_pt = punctF.decimal_point(); thou_sep = punctF.thousands_sep(); frac_dig = punctF.frac_digits(); grp = punctF.grouping(); } string_type& sign = pos_sign; money_base::pattern& pat = pos_pat; bool sign_ = false; ios_base::fmtflags flags_sav; int tmp, prec_sav, space_pos; string_type str; // read the format from moneypunct if (units < 0) { pat = neg_pat; sign = neg_sign; units = -units; } for (int i = 0; i < 4; ++i) { switch (pat.field[i]) { case money_base::symbol: if (io.flags() & ios_base::showbase) str.append(curr_sym); break; case money_base::sign: if (sign.size() <= 1) str.append(sign); else { str.append(1, sign[0]); sign_ = true; } break; case money_base::space: space_pos = str.size(); str.append(1, fill); break; case money_base::value: { tmp = frac_dig; while (tmp--) units /= 10.0L; prec_sav = io.precision(frac_dig); flags_sav = io.flags(ios_base::no_flags); io.setf (ios_base::fixed | ios_base::dec); char fmt[16]; __kai::build_fmt(io, fmt, 4); char buf[200]; sprintf(buf, fmt, units); io.precision(prec_sav); io.flags(flags_sav); string_type _units = __kai::convert_locale_string( buf ); str.append(__kai::insert_thsep(_units, grp, thou_sep, dec_pt)); break; } case money_base::none: space_pos = str.size(); str.append(1, fill); break; default: break; } } if (sign_) str.append(sign.data()+1); int count = 0; count += str.size(); count = io.width() - count; // padding to the specific width if (count > 0) { int pos; switch (io.flags() & ios_base::adjustfield) { case ios_base::left: pos = str.size(); break; case ios_base::right: pos = 0; break; case ios_base::internal: pos = space_pos; break; } str.insert(pos, count, fill); } size_t cnt = 0; while (cnt < str.size ()) { *iter++ = str[cnt]; ++cnt; } return iter; } template money_put::iter_type money_put:: do_put(iter_type iter, bool international, ios_base& io, char_type fill, const string_type& digits) const { typedef string_type::traits_type straits_type; const locale& loc = io.getloc(); const ctype& ct = use_facet >(loc); const charT * D = digits.c_str(); bool isNeg = false; if (straits_type::eq(*D, '-')) { isNeg = true; ++D; } else if (straits_type::eq(*D, '+')) ++D; long double value = 0.0L; for (size_t pos = 0; isdigit(D[pos], loc); ++pos) value = (value * 10) + (ct.narrow(D[pos],0)-'0'); if (isNeg) value = -value; return do_put(iter, international, io, fill, value); } // MESSAGES CATEGORY #ifdef MSIPL_NL_TYPES class messages_base { public: typedef nl_catd catalog; }; template class messages : public locale::facet, public messages_base { public: typedef charT char_type; typedef basic_string, allocator > string_type; explicit messages(size_t refs = 0) : locale::facet(refs) { } catalog open(const basic_string, allocator >& fn, const locale& loc) const { return do_open (fn, loc); } string_type get(catalog c, int set, int msgid, const string_type& dfault) const { return do_get(c, set, msgid, dfault); } void close(catalog c) const { return do_close(c); } static locale::id id; protected: ~messages(); virtual catalog do_open (const basic_string, allocator >& fn, const locale& loc) const; virtual string_type do_get(catalog c, int set, int msgid, const string_type& dfault) const; virtual void do_close(catalog c) const; }; template class messages_byname : public messages { public: explicit messages_byname(const char*, size_t refs = 0); protected: ~messages_byname(); virtual catalog do_open(const basic_string, allocator >& str, const locale& loc) const { return messages::do_open (str, loc); } virtual string_type do_get(catalog cat, int set, int msgid, const string_type& dfault) const { return messages::do_get(cat, set, msgid, dfault); } virtual void do_close(catalog cat) const { return messages::do_close(cat); } }; template inline messages::catalog messages:: do_open (const basic_string, allocator >& name, const locale& loc) const { nl_catd cat = ::catopen (name.c_str(), 0); assert(cat != (nl_catd) -1); return cat; } template inline messages::string_type messages:: do_get(catalog cat, int set, int msgid, const string_type& dfault) const { const charT* dflt = dfault.c_str(); const char* ret = ::catgets(cat, set, msgid, dflt); return ret; } template inline void messages::do_close(catalog cat) const { int ret = ::catclose(cat); assert(ret != -1); } #endif /* MSIPL_NL_TYPES */ template inline bool locale::operator()(const basic_string& s1, const basic_string& s2) const { const std::collate& col = use_facet >(*this); return (col.compare(s1.data(), s1.data()+ s1.size(), s2.data(), s2.data() + s2.size()) < 0); } template inline basic_ostream& operator<<(basic_ostream& os, const locale& loc) { return os << loc.name() << endl; } template basic_istream& operator>>(basic_istream& is, locale& loc) { typedef basic_string, allocator > string_type; string_type str; is >> str; // read the locale's name if (setlocale(LC_ALL, str.c_str()) != 0) loc = locale(str.c_str()); // try to construct the locale else is.setstate(ios_base::failbit); return is; } } // namespace std #endif /* __KAI_LOCALE */