// file : xsd/cxx/parser/non-validating/xml-schema-pimpl.txx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include #include namespace xsd { namespace cxx { namespace parser { namespace non_validating { // Note that most of the types implemented here cannot have // whitespaces in the value. As result we don't need to waste // time collapsing whitespaces. All we need to do is trim the // string representation which can be done without copying. // // any_type // template void any_type_pimpl:: post_any_type () { } // any_simple_type // template void any_simple_type_pimpl:: post_any_simple_type () { } // boolean // template void boolean_pimpl:: _pre () { str_.clear (); } template void boolean_pimpl:: _characters (const ro_string& s) { str_ += s; } template bool boolean_pimpl:: post_boolean () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); return str == bits::true_ () || str == bits::one (); } // byte // template void byte_pimpl:: _pre () { str_.clear (); } template void byte_pimpl:: _characters (const ro_string& s) { str_ += s; } template signed char byte_pimpl:: post_byte () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); short t; zc_istream is (str); is >> t; return static_cast (t); } // unsigned_byte // template void unsigned_byte_pimpl:: _pre () { str_.clear (); } template void unsigned_byte_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned char unsigned_byte_pimpl:: post_unsigned_byte () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned short t; zc_istream is (str); is >> t; return static_cast (t); } // short // template void short_pimpl:: _pre () { str_.clear (); } template void short_pimpl:: _characters (const ro_string& s) { str_ += s; } template short short_pimpl:: post_short () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); short t; zc_istream is (str); is >> t; return t; } // unsigned_short // template void unsigned_short_pimpl:: _pre () { str_.clear (); } template void unsigned_short_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned short unsigned_short_pimpl:: post_unsigned_short () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned short t; zc_istream is (str); is >> t; return t; } // int // template void int_pimpl:: _pre () { str_.clear (); } template void int_pimpl:: _characters (const ro_string& s) { str_ += s; } template int int_pimpl:: post_int () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); int t; zc_istream is (str); is >> t; return t; } // unsigned_int // template void unsigned_int_pimpl:: _pre () { str_.clear (); } template void unsigned_int_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned int unsigned_int_pimpl:: post_unsigned_int () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned int t; zc_istream is (str); is >> t; return t; } // long // template void long_pimpl:: _pre () { str_.clear (); } template void long_pimpl:: _characters (const ro_string& s) { str_ += s; } template long long long_pimpl:: post_long () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); long long t; zc_istream is (str); is >> t; return t; } // unsigned_long // template void unsigned_long_pimpl:: _pre () { str_.clear (); } template void unsigned_long_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned long long unsigned_long_pimpl:: post_unsigned_long () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned long long t; zc_istream is (str); is >> t; return t; } // integer // template void integer_pimpl:: _pre () { str_.clear (); } template void integer_pimpl:: _characters (const ro_string& s) { str_ += s; } template long long integer_pimpl:: post_integer () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); long long t; zc_istream is (str); is >> t; return t; } // negative_integer // template void negative_integer_pimpl:: _pre () { str_.clear (); } template void negative_integer_pimpl:: _characters (const ro_string& s) { str_ += s; } template long long negative_integer_pimpl:: post_negative_integer () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); long long t; zc_istream is (str); is >> t; return t; } // non_positive_integer // template void non_positive_integer_pimpl:: _pre () { str_.clear (); } template void non_positive_integer_pimpl:: _characters (const ro_string& s) { str_ += s; } template long long non_positive_integer_pimpl:: post_non_positive_integer () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); long long t; zc_istream is (str); is >> t; return t; } // positive_integer // template void positive_integer_pimpl:: _pre () { str_.clear (); } template void positive_integer_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned long long positive_integer_pimpl:: post_positive_integer () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned long long t; zc_istream is (str); is >> t; return t; } // non_negative_integer // template void non_negative_integer_pimpl:: _pre () { str_.clear (); } template void non_negative_integer_pimpl:: _characters (const ro_string& s) { str_ += s; } template unsigned long long non_negative_integer_pimpl:: post_non_negative_integer () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); unsigned long long t; zc_istream is (str); is >> t; return t; } // float // template void float_pimpl:: _pre () { str_.clear (); } template void float_pimpl:: _characters (const ro_string& s) { str_ += s; } template float float_pimpl:: post_float () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); if (str == bits::positive_inf ()) return std::numeric_limits::infinity (); if (str == bits::negative_inf ()) return -std::numeric_limits::infinity (); if (str == bits::nan ()) return std::numeric_limits::quiet_NaN (); float t; zc_istream is (str); is.imbue (std::locale::classic ()); is >> t; return t; } // double // template void double_pimpl:: _pre () { str_.clear (); } template void double_pimpl:: _characters (const ro_string& s) { str_ += s; } template double double_pimpl:: post_double () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); if (str == bits::positive_inf ()) return std::numeric_limits::infinity (); if (str == bits::negative_inf ()) return -std::numeric_limits::infinity (); if (str == bits::nan ()) return std::numeric_limits::quiet_NaN (); double t; zc_istream is (str); is.imbue (std::locale::classic ()); is >> t; return t; } // decimal // template void decimal_pimpl:: _pre () { str_.clear (); } template void decimal_pimpl:: _characters (const ro_string& s) { str_ += s; } template double decimal_pimpl:: post_decimal () { std::basic_string tmp; tmp.swap (str_); ro_string str (tmp); trim (str); double t; zc_istream is (str); is.imbue (std::locale::classic ()); is >> t; return t; } // string // template void string_pimpl:: _pre () { str_.clear (); } template void string_pimpl:: _characters (const ro_string& s) { str_ += s; } template std::basic_string string_pimpl:: post_string () { std::basic_string r; r.swap (str_); return r; } // normalized_string // template void normalized_string_pimpl:: _pre () { str_.clear (); } template void normalized_string_pimpl:: _characters (const ro_string& s) { str_ += s; } template std::basic_string normalized_string_pimpl:: post_normalized_string () { typedef typename std::basic_string::size_type size_type; size_type size (str_.size ()); for (size_type i (0); i < size; ++i) { C& c = str_[i]; if (c == C (0x0A) || c == C (0x0D) || c == C (0x09)) c = C (0x20); } std::basic_string r; r.swap (str_); return r; } // token // template void token_pimpl:: _pre () { str_.clear (); } template void token_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string token_pimpl:: post_token () { typedef typename std::basic_string::size_type size_type; size_type size (str_.size ()); size_type j (0); bool subs (false); for (size_type i (0); i < size; ++i) { C c = str_[i]; if (c == C (0x20) || c == C (0x0A) || c == C (0x0D) || c == C (0x09)) { subs = true; } else { if (subs) { subs = false; str_[j++] = C (0x20); } str_[j++] = c; } } str_.resize (j); std::basic_string r; r.swap (str_); return r; } // name // template void name_pimpl:: _pre () { str_.clear (); } template void name_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string name_pimpl:: post_name () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // nmtoken // template void nmtoken_pimpl:: _pre () { str_.clear (); } template void nmtoken_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string nmtoken_pimpl:: post_nmtoken () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // nmtokens // template void nmtokens_pimpl:: _pre () { nmtokens_pskel::_pre (); seq_.clear (); } template string_sequence nmtokens_pimpl:: post_nmtokens () { string_sequence r; r.swap (seq_); return r; } template void nmtokens_pimpl:: _xsd_parse_item (const ro_string& s) { parser_.pre (); parser_._pre (); parser_._characters (s); parser_._post (); seq_.push_back (parser_.post_nmtoken ()); } // ncname // template void ncname_pimpl:: _pre () { str_.clear (); } template void ncname_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string ncname_pimpl:: post_ncname () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // id // template void id_pimpl:: _pre () { str_.clear (); } template void id_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string id_pimpl:: post_id () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // idref // template void idref_pimpl:: _pre () { str_.clear (); } template void idref_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string idref_pimpl:: post_idref () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // idrefs // template void idrefs_pimpl:: _pre () { idrefs_pskel::_pre (); seq_.clear (); } template string_sequence idrefs_pimpl:: post_idrefs () { string_sequence r; r.swap (seq_); return r; } template void idrefs_pimpl:: _xsd_parse_item (const ro_string& s) { parser_.pre (); parser_._pre (); parser_._characters (s); parser_._post (); seq_.push_back (parser_.post_idref ()); } // language // template void language_pimpl:: _pre () { str_.clear (); } template void language_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string language_pimpl:: post_language () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // uri // template void uri_pimpl:: _pre () { str_.clear (); } template void uri_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template std::basic_string uri_pimpl:: post_uri () { ro_string tmp (str_); str_.resize (trim_right (tmp)); std::basic_string r; r.swap (str_); return r; } // qname // template void qname_pimpl:: _pre () { str_.clear (); } template void qname_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template qname qname_pimpl:: post_qname () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); size_type pos (tmp.find (C (':'))); if (pos != ro_string::npos) { std::basic_string prefix (tmp.data (), pos++); std::basic_string name (tmp.data () + pos, size - pos); return qname (prefix, name); } else { str_.resize (size); return qname (str_); } } // base64_binary // template void base64_binary_pimpl:: _pre () { str_.clear (); } template void base64_binary_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } namespace bits { template inline unsigned char base64_decode (C c) { unsigned char r (0xFF); if (c >= C('A') && c <= C ('Z')) r = static_cast (c - C ('A')); else if (c >= C('a') && c <= C ('z')) r = static_cast (c - C ('a') + 26); else if (c >= C('0') && c <= C ('9')) r = static_cast (c - C ('0') + 52); else if (c == C ('+')) r = 62; else if (c == C ('/')) r = 63; return r; } } template std::auto_ptr base64_binary_pimpl:: post_base64_binary () { typedef typename std::basic_string::size_type size_type; size_type size (str_.size ()); const C* src (str_.c_str ()); // Remove all whitespaces. // { size_type j (0); bool subs (false); for (size_type i (0); i < size; ++i) { C c = str_[i]; if (c == C (0x20) || c == C (0x0A) || c == C (0x0D) || c == C (0x09)) { subs = true; } else { if (subs) subs = false; str_[j++] = c; } } size = j; str_.resize (size); } // Our length should be a multiple of four. // size_type quad_count (size / 4); size_type capacity (quad_count * 3 + 1); std::auto_ptr buf (new buffer (capacity, capacity)); char* dst (buf->data ()); size_type si (0), di (0); // Source and destination indexes. // Process all quads except the last one. // unsigned char b1, b2, b3, b4; for (size_type q (0); q < quad_count - 1; ++q) { b1 = bits::base64_decode (src[si++]); b2 = bits::base64_decode (src[si++]); b3 = bits::base64_decode (src[si++]); b4 = bits::base64_decode (src[si++]); dst[di++] = (b1 << 2) | (b2 >> 4); dst[di++] = (b2 << 4) | (b3 >> 2); dst[di++] = (b3 << 6) | b4; } // Process the last quad. The first two octets are always there. // b1 = bits::base64_decode (src[si++]); b2 = bits::base64_decode (src[si++]); C e3 (src[si++]); C e4 (src[si++]); if (e4 == C ('=')) { if (e3 == C ('=')) { // Two pads. Last 4 bits in b2 should be zero. // dst[di++] = (b1 << 2) | (b2 >> 4); } else { // One pad. Last 2 bits in b3 should be zero. // b3 = bits::base64_decode (e3); dst[di++] = (b1 << 2) | (b2 >> 4); dst[di++] = (b2 << 4) | (b3 >> 2); } } else { // No pads. // b3 = bits::base64_decode (e3); b4 = bits::base64_decode (e4); dst[di++] = (b1 << 2) | (b2 >> 4); dst[di++] = (b2 << 4) | (b3 >> 2); dst[di++] = (b3 << 6) | b4; } // Set the real size. // buf->size (di); return buf; } // hex_binary // template void hex_binary_pimpl:: _pre () { str_.clear (); } template void hex_binary_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } namespace bits { template inline unsigned char hex_decode (C c) { unsigned char r (0xFF); if (c >= C('0') && c <= C ('9')) r = static_cast (c - C ('0')); else if (c >= C ('A') && c <= C ('F')) r = static_cast (10 + (c - C ('A'))); else if (c >= C ('a') && c <= C ('f')) r = static_cast (10 + (c - C ('a'))); return r; } } template std::auto_ptr hex_binary_pimpl:: post_hex_binary () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); buffer::size_t n (size / 2); std::auto_ptr buf (new buffer (n)); const C* src (tmp.data ()); char* dst (buf->data ()); for (buffer::size_t i (0); i < n; ++i) { unsigned char h (bits::hex_decode (src[2 * i])); unsigned char l (bits::hex_decode (src[2 * i + 1])); dst[i] = (h << 4) | l; } return buf; } // time_zone // namespace bits { // Datatypes 3.2.7.3. // template void parse_tz (const C* s, typename std::basic_string::size_type n, short& h, short& m) { // time_zone := Z|(+|-)HH:MM // if (n == 0) { return; } else if (s[0] == 'Z') { h = 0; m = 0; } else if (n == 6) { // Parse hours. // h = 10 * (s[1] - '0') + (s[2] - '0'); // Parse minutes. // m = 10 * (s[4] - '0') + (s[5] - '0'); if (s[0] == '-') { h = -h; m = -m; } } } } // gday // template void gday_pimpl:: _pre () { str_.clear (); } template void gday_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template gday gday_pimpl:: post_gday () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); unsigned short day (0); bool z (false); short zh (0), zm (0); // gday := ---DD[Z|(+|-)HH:MM] // if (size >= 5) { day = 10 * (s[3] - '0') + (s[4] - '0'); if (size > 5) { bits::parse_tz (s + 5, size - 5, zh, zm); z = true; } } return z ? gday (day, zh, zm) : gday (day); } // gmonth // template void gmonth_pimpl:: _pre () { str_.clear (); } template void gmonth_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template gmonth gmonth_pimpl:: post_gmonth () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); unsigned short month (0); bool z (false); short zh (0), zm (0); // gmonth := --MM[Z|(+|-)HH:MM] // if (size >= 4) { month = 10 * (s[2] - '0') + (s[3] - '0'); if (size > 4) { bits::parse_tz (s + 4, size - 4, zh, zm); z = true; } } return z ? gmonth (month, zh, zm) : gmonth (month); } // gyear // template void gyear_pimpl:: _pre () { str_.clear (); } template void gyear_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template gyear gyear_pimpl:: post_gyear () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); int year (0); bool z (false); short zh (0), zm (0); // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] // if (size >= 4) { // Find the end of the year token. // size_type pos (4); for (; pos < size; ++pos) { C c (s[pos]); if (c == C ('Z') || c == C ('+') || c == C ('-')) break; } ro_string year_fragment (s, pos); zc_istream is (year_fragment); is >> year; if (pos < size) { bits::parse_tz (s + pos, size - pos, zh, zm); z = true; } } return z ? gyear (year, zh, zm) : gyear (year); } // gmonth_day // template void gmonth_day_pimpl:: _pre () { str_.clear (); } template void gmonth_day_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template gmonth_day gmonth_day_pimpl:: post_gmonth_day () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); unsigned short month (0), day (0); bool z (false); short zh (0), zm (0); // gmonth_day := --MM-DD[Z|(+|-)HH:MM] // if (size >= 7) { month = 10 * (s[2] - '0') + (s[3] - '0'); day = 10 * (s[5] - '0') + (s[6] - '0'); if (size > 7) { bits::parse_tz (s + 7, size - 7, zh, zm); z = true; } } return z ? gmonth_day (month, day, zh, zm) : gmonth_day (month, day); } // gyear_month // template void gyear_month_pimpl:: _pre () { str_.clear (); } template void gyear_month_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template gyear_month gyear_month_pimpl:: post_gyear_month () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); int year (0); unsigned short month (0); bool z (false); short zh (0), zm (0); // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] // if (size >= 7) { // Find the end of the year token. // size_type pos (tmp.find (C ('-'), 4)); if (pos != ro_string::npos && (size - pos - 1) >= 2) { ro_string year_fragment (s, pos); zc_istream yis (year_fragment); yis >> year; month = 10 * (s[pos + 1] - '0') + (s[pos + 2] - '0'); pos += 3; if (pos < size) { bits::parse_tz (s + pos, size - pos, zh, zm); z = true; } } } return z ? gyear_month (year, month, zh, zm) : gyear_month (year, month); } // date // template void date_pimpl:: _pre () { str_.clear (); } template void date_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template date date_pimpl:: post_date () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); int year (0); unsigned short month (0), day (0); bool z (false); short zh (0), zm (0); // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] // if (size >= 10) { // Find the end of the year token. // size_type pos (tmp.find (C ('-'), 4)); if (pos != ro_string::npos && (size - pos - 1) >= 5) { ro_string year_fragment (s, pos); zc_istream yis (year_fragment); yis >> year; month = 10 * (s[pos + 1] - '0') + (s[pos + 2] - '0'); day = 10 * (s[pos + 4] - '0') + (s[pos + 5] - '0'); pos += 6; if (pos < size) { bits::parse_tz (s + pos, size - pos, zh, zm); z = true; } } } return z ? date (year, month, day, zh, zm) : date (year, month, day); } // time // template void time_pimpl:: _pre () { str_.clear (); } template void time_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template time time_pimpl:: post_time () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); unsigned short hours (0), minutes (0); double seconds (0.0); bool z (false); short zh (0), zm (0); // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] // if (size >= 8) { hours = 10 * (s[0] - '0') + (s[1] - '0'); minutes = 10 * (s[3] - '0') + (s[4] - '0'); // Find the end of the seconds fragment. // size_type pos (8); for (; pos < size; ++pos) { C c (s[pos]); if (c == C ('Z') || c == C ('+') || c == C ('-')) break; } ro_string seconds_fragment (s + 6, pos - 6); zc_istream sis (seconds_fragment); sis >> seconds; if (pos < size) { bits::parse_tz (s + pos, size - pos, zh, zm); z = true; } } return z ? time (hours, minutes, seconds, zh, zm) : time (hours, minutes, seconds); } // date_time // template void date_time_pimpl:: _pre () { str_.clear (); } template void date_time_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } template date_time date_time_pimpl:: post_date_time () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); const C* s (tmp.data ()); int year (0); unsigned short month (0), day (0), hours (0), minutes (0); double seconds (0.0); bool z (false); short zh (0), zm (0); // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] // if (size >= 19) { // Find the end of the year token. // size_type pos (tmp.find (C ('-'), 4)); if (pos != ro_string::npos && (size - pos - 1) >= 14) { ro_string year_fragment (s, pos); zc_istream yis (year_fragment); yis >> year; month = 10 * (s[pos + 1] - '0') + (s[pos + 2] - '0'); day = 10 * (s[pos + 4] - '0') + (s[pos + 5] - '0'); pos += 7; // Point to the first H. hours = 10 * (s[pos] - '0') + (s[pos + 1] - '0'); minutes = 10 * (s[pos + 3] - '0') + (s[pos + 4] - '0'); // Find the end of the seconds fragment. // pos += 6; // Point to the first S. size_type sec_end (pos + 2); for (; sec_end < size; ++sec_end) { C c (s[sec_end]); if (c == C ('Z') || c == C ('+') || c == C ('-')) break; } ro_string seconds_fragment (s + pos, sec_end - pos); zc_istream sis (seconds_fragment); sis >> seconds; if (sec_end < size) { bits::parse_tz (s + sec_end, size - sec_end, zh, zm); z = true; } } } return z ? date_time (year, month, day, hours, minutes, seconds, zh, zm) : date_time (year, month, day, hours, minutes, seconds); } // duration // template void duration_pimpl:: _pre () { str_.clear (); } template void duration_pimpl:: _characters (const ro_string& s) { if (str_.size () == 0) { ro_string tmp (s.data (), s.size ()); if (trim_left (tmp) != 0) str_ += tmp; } else str_ += s; } namespace bits { template inline typename ro_string::size_type duration_delim (const C* s, typename ro_string::size_type pos, typename ro_string::size_type size) { const C* p (s + pos); for (; p < (s + size); ++p) { if (*p == C ('Y') || *p == C ('D') || *p == C ('M') || *p == C ('H') || *p == C ('M') || *p == C ('S') || *p == C ('T')) break; } return p - s; } } template duration duration_pimpl:: post_duration () { typedef typename ro_string::size_type size_type; ro_string tmp (str_); size_type size (trim_right (tmp)); bool negative (false); unsigned int years (0), months (0), days (0), hours (0), minutes (0); double seconds (0.0); // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] // const C* s (tmp.data ()); if (size >= 3) { size_type pos (0); if (s[0] == C ('-')) { negative = true; pos++; } pos++; // Skip 'P'. size_type del (bits::duration_delim (s, pos, size)); if (del != size && s[del] == C ('Y')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> years; pos = del + 1; del = bits::duration_delim (s, pos, size); } if (del != size && s[del] == C ('M')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> months; pos = del + 1; del = bits::duration_delim (s, pos, size); } if (del != size && s[del] == C ('D')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> days; pos = del + 1; del = bits::duration_delim (s, pos, size); } if (del != size && s[del] == C ('T')) { pos = del + 1; del = bits::duration_delim (s, pos, size); if (del != size && s[del] == C ('H')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> hours; pos = del + 1; del = bits::duration_delim (s, pos, size); } if (del != size && s[del] == C ('M')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> minutes; pos = del + 1; del = bits::duration_delim (s, pos, size); } if (del != size && s[del] == C ('S')) { ro_string fragment (s + pos, del - pos); zc_istream is (fragment); is >> seconds; } } } return duration ( negative, years, months, days, hours, minutes, seconds); } } } } }