inline std::basic_istream<CharType, CharTrait>& operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v) { if (in.good()) { int d = in.get(); if (d == ' ') { T x; in >> x; #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES v = boost::move(x); #else v = x; #endif }
inline SPROUT_NON_CONSTEXPR std::basic_istream<Elem, Traits>& operator>>(std::basic_istream<Elem, Traits>& lhs, sprout::rational<IntType>& rhs) { IntType n = IntType(0); IntType d = IntType(1); Elem c = 0; sprout::detail::io::ios_flags_saver saver(lhs); lhs >> n; c = lhs.get(); if (c != Elem('/')) { lhs.clear(std::istream::badbit); } lhs >> std::noskipws; lhs >> d; if (lhs) { rhs.assign(n, d); } return lhs; }
std::basic_istream<charT, Traits>& operator>>(std::basic_istream<charT, Traits>& in, token_matcher<charT, Traits, Allocator> matcher) { typename std::basic_string<charT, Traits, Allocator>::iterator i = matcher.token.begin(), end = matcher.token.end(); typename std::basic_istream<charT, Traits>::char_type c; for (; i != end && in.get(c); ++i) { if (*i != c) { in.clear(std::basic_ios<charT, Traits>::failbit); break; } } return in; }
std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& in, pcg128_t& value) { typename std::basic_istream<CharT,Traits>::sentry s(in); if (!s) return in; constexpr auto BASE = pcg128_t(10ULL); pcg128_t current(0ULL); bool did_nothing = true; bool overflow = false; for(;;) { CharT wide_ch = in.get(); if (!in.good()) break; auto ch = in.narrow(wide_ch, '\0'); if (ch < '0' || ch > '9') { in.unget(); break; } did_nothing = false; pcg128_t digit(uint32_t(ch - '0')); pcg128_t timesbase = current*BASE; overflow = overflow || timesbase < current; current = timesbase + digit; overflow = overflow || current < digit; } if (did_nothing || overflow) { in.setstate(std::ios::failbit); if (overflow) current = ~pcg128_t(0ULL); } value = current; return in; }
void parse(std::basic_istream<CharT> &src, HandlerT &handler) { enum Action { Stay, Skip }; const int eos = -1; typedef std::function<Action (int)> parser_t; parser_t rule, top, in_string, in_atom, in_comment, append_escaped, append_escaped_hex; stack<parser_t> ctx; unsigned level = 0; std::string data; int hex_byte; auto rule_use = [&](parser_t const &p) { data = ""; data.reserve(256); rule = p; }; auto rule_pop = [&]() { auto p = ctx.top(); ctx.pop(); rule = p; }; auto rule_push = [&](parser_t const &after, parser_t const ¤t) { ctx.push(after); rule = current; }; top = [&](int c) -> Action { if (c == ')') { if (!level) throw Error(src, "Unexpected ')'"); --level; handler.on_list_end(); } else if (c == '(') { ++level; handler.on_list_begin(); } else if (c == ';') { rule_use(in_comment); } else if (::isspace(c)) { // do nothing } else if (c == '"') { rule_use(in_string); } else if (c != eos) { rule_use(in_atom); return Stay; } return Skip; }; in_comment = [&](int c) -> Action { if (c != '\n' && c != eos) { data += c; } else { handler.on_comment(std::move(data)); rule_use(top); } return Skip; }; auto in_hex = [&](int c) -> Action { if (c != eos) { int n = char2hex(c); if (n >= 0) { if (hex_byte < 0) { hex_byte = (n << 4); return Skip; } hex_byte |= n; } } rule_pop(); return Stay; }; append_escaped_hex = [&](int) -> Action { if (hex_byte < 0) throw Error(src, "Escaped hex is empty"); data += static_cast<char>(hex_byte); rule_pop(); return Stay; }; auto process_hex = [&](parser_t const &after) -> Action { hex_byte = -1; rule_push(after, in_hex); return Skip; }; append_escaped = [&](int c) -> Action { static const std::unordered_map<char, char> assoc{{'n', '\n'}, {'t', '\t'}, {'r', '\r'}, {'a', '\a'}, {'b', '\b'}, {'v', '\v'}}; if (c == eos) throw Error(src, "Expected escaped symbol, got EOS"); if (c == 'x') return process_hex(append_escaped_hex); auto p = assoc.find(c); if (p != assoc.end()) { data += p->second; } else { data += c; } rule_pop(); return Skip; }; auto process_escaped = [&]() -> Action { rule_push(rule, append_escaped); return Skip; }; in_atom = [&](int c) -> Action { static const std::string bound("()"); if (bound.find(c) != std::string::npos || isspace(c) || c == eos) { handler.on_atom(std::move(data)); rule_use(top); return Stay; } else if (c == '\\') { return process_escaped(); } else { data += c; } return Skip; }; in_string = [&](int c) -> Action { if (c == '"') { handler.on_string(std::move(data)); rule_use(top); } else if (c == '\\') { return process_escaped(); } else if (c == eos) { throw Error(src, "string is not limited, got EOS"); } else { data += c; } return Skip; }; rule_use(top); try { while (true) { CharT c = src.get(); if (src.gcount() == 0) { rule(eos); break; } while (rule(c) == Stay) {} } } catch (Error const &e) { throw; } catch (std::exception const &e) { throw; } handler.on_eof(); }
/** * @brief Deserialize the string value from the specified input stream. * @param __s Reference to the input stream. */ void load(std::basic_istream<CharT, Traits>& __s) { // Define the integer symbol representation placeholder. std::basic_stringstream<CharT, Traits> __i; // Define the input stream iterator of the provided stream to // be able to read the string length value symbol by symbol. auto __si = std::istream_iterator<CharT, CharT, Traits>(__s); // Define the output stream to as a buffer for the integer // value, which will be later converted. auto __ival = std::ostream_iterator<CharT, CharT, Traits>(__i); // Copy the symbols from the input stream to the integer // placeholder until the ":" delimiter value. auto __result = copy_until(__si, __ival, [&__s](const CharT& __ch) { // Additionally, check that we did not exceed the // length of the stream to prevent hangs. return !__s.eof() && __ch != basic_value_type::delimiter_token; }, basic_value_type::integer_length); if (*__result != basic_value_type::delimiter_token) { std::ostringstream __error; __error << "bencode::string::load the delimiter `:` " "expected, but `" << CharT(*__result) << "` found\n"; throw encoding_error(__error.str()); } // Save the length of the string. int64_t __count; __i >> __count; if (!__count && __i.str() != std::basic_string< CharT, Traits>(1, CharT('0'))) { std::ostringstream __error; __error << "bencode::string::load the specified string " "length is not a number\n"; throw value_error(__error.str()); } // Ensure that the string length is a non-negative value. if (__count < 0) { std::ostringstream __error; __error << "bencode::string::load the length of the string " "value must be a positive integer: `" << __count << "`\n"; throw value_error(__error.str()); } // Allocate the list of symbols of the specified string length. std::unique_ptr<CharT[]> __str(new CharT[__count+1]); // Read the string value into the symbol list. __s.get(__str.get(), std::streamsize(__count+1)); auto __strval = string_type(__str.get()); // Ensure that valid count of the symbols was extracted from // the provided input stream. if (int64_t(__strval.length()) != __count) { std::ostringstream __error; __error << "bencode::string::load the specified string " "decoded length is not equal to the real one: `" << __count << "` != `" << __strval.length() << "`\n"; throw value_error(__error.str()); } // Initialize the internal value with a new string. _M_value = __strval; }