#include #include #include using namespace std; typedef unsigned short UC; class uctype : public locale::facet, public ctype_base { public: static locale::id id; typedef UC char_type; uctype(size_t refs = 0): locale::facet(refs) {} public: bool is(mask m, UC c) const; const UC *is(const UC *low, const UC *high, mask *vec) const; const UC *scan_is(mask m, const UC *low, const UC *high) const; const UC *scan_not(mask m, const UC *low, const UC *high) const; UC toupper(UC c) const; const UC *toupper(UC *low, const UC *high) const; UC tolower(UC c) const; const UC *tolower(UC *low, const UC *high) const; UC widen(char) const; const char *widen(const char *low, const char *high, UC *dest) const; char narrow(UC, char defchar) const; const UC *narrow(const UC *low, const UC *high, char defchar, char *dest) const; }; locale::id uctype::id; static const UC char_limit(0x100); class ClassicCtype { public: typedef ctype::mask mask_t; ClassicCtype() { const ctype& classic = use_facet >(locale::classic()); char buf[char_limit]; for (int i = 0; i < char_limit; ++i) buf[i] = i; classic.is(buf, buf + char_limit, masks_); memcpy(uppercases_, buf, char_limit); classic.toupper(uppercases_, uppercases_ + char_limit); memcpy(lowercases_, buf, char_limit); classic.tolower(lowercases_, lowercases_ + char_limit); } mask_t mask(UC c) const { return (c >= char_limit ? mask_t() : masks_[c]); } UC toupper(UC c) const { return (c >= char_limit ? c : uppercases_[c]); } UC tolower(UC c) const { return (c >= char_limit ? c : lowercases_[c]); } protected: mask_t masks_[char_limit]; char uppercases_[char_limit], lowercases_[char_limit]; }; static ClassicCtype classic_ctype; bool uctype::is(mask m, UC c) const { return static_cast(classic_ctype.mask(c) & m); } const UC *uctype::is(const UC *low, const UC *high, mask *vec) const { while (low != high) *vec++ = classic_ctype.mask(*low++); return high; } const UC *uctype::scan_is(mask m, const UC *low, const UC *high) const { while (low != high) { if (classic_ctype.mask(*low) & m) break; ++low; } return low; } const UC *uctype::scan_not(mask m, const UC *low, const UC *high) const { while (low != high) { if (!(classic_ctype.mask(*low) & m)) break; ++low; } return low; } UC uctype::toupper(UC c) const { return classic_ctype.toupper(c); } const UC *uctype::toupper(UC *low, const UC *high) const { while (low != high) { *low = classic_ctype.toupper(*low); ++low; } return low; } UC uctype::tolower(UC c) const { return classic_ctype.tolower(c); } const UC *uctype::tolower(UC *low, const UC *high) const { while (low != high) { *low = classic_ctype.tolower(*low); ++low; } return low; } UC uctype::widen(char c) const { return static_cast(static_cast(c)); } const char *uctype::widen(const char *low, const char *high, UC *dest) const { while (low != high) *dest++ = static_cast(static_cast(*low++)); return low; } char uctype::narrow(UC c, char defchar) const { if (c >= char_limit) return defchar; return static_cast(c); } const UC *uctype::narrow(const UC *low, const UC *high, char defchar, char *dest) const { while (low != high) { *dest = (*low >= char_limit ? defchar : static_cast(*low)); ++low; ++dest; } return low; } namespace std { template <> class ctype : public uctype { public: ctype(size_t refs=0): uctype(refs) {} }; } int main() { basic_ostringstream oss; oss.imbue(locale(locale(locale(), new ctype), new num_put)); oss << 42; basic_string s = oss.str(); cout << s.length(); return 0; }