# # # add_file "io.cc" # content [b0753ee961d8799ad24f008d6497132fc07ad9c2] # # add_file "io.hh" # content [ccad8be31096e6ca11cae88425b5986ea258f07c] # ============================================================ --- io.cc b0753ee961d8799ad24f008d6497132fc07ad9c2 +++ io.cc b0753ee961d8799ad24f008d6497132fc07ad9c2 @@ -0,0 +1,157 @@ +// 2006-04-13 Timothy Brownawell +// +// The basic_io implementation in monotone represents basic_io as a +// token stream. This represents it as a data structure. +// Also, this allows i/o to/from iostreams, not just strings. + +#include "io.hh" + + +using namespace basic_io; + +istream &basic_io::operator>>(istream &in, value &v) +{ + v.literal.clear(); + v.parsed.clear(); + char c; + in.get(c); + if (c == '[') + { + v.literal = c; + while (in.get(c) && std::isxdigit(c)) + { + v.literal += c; + v.parsed += c; + } + if (c == ']') + v.literal += c; + else + in.setstate(std::ios_base::failbit);//parse error + } + else if (c == '"') + { + v.literal = c; + while (in.get(c) && c != '"') + { + if (c == '\\') + { + v.literal += c; + in.get(c); + } + v.literal += c; + v.parsed += c; + } + if (c == '"') + v.literal += c; + else + in.setstate(std::ios_base::failbit);//parse error + } + else + { + in.unget(); + } + return in; +} +ostream &basic_io::operator<<(ostream &out, value &v) +{ + out<>(istream &in, item &i) +{ + i.key.clear(); + i.values.clear(); + bool got_key = false, done = false; + char c; + in >> c; + if (!in) + return in; + in.unget(); + do + { + if ((c == '[' || c == '"') && got_key) + { + value v; + in >> v; + i.values.push_back(v); + } + else if (!got_key && c != '[' && c != '"') + { + in >> i.key; + i.longest = i.key.size(); + got_key = true; + } + else + done = true; + bool ok = in; + in >> c; + in.unget(); + if (ok && !in) + { + in.clear(); + done = true; + } + } + while (!done && in); + return in; +} +ostream &basic_io::operator<<(ostream &out, item const &i) +{ + out<::const_iterator j = i.values.begin(); + j != i.values.end(); ++j) + { + out << " " << j->literal; + } + out<<"\n"; + return out; +} + +void +stanza::compute_longest() +{ + unsigned int longest=0; + for (vector::const_iterator i = items.begin(); + i != items.end(); ++i) + { + longest=(i->key.size()>longest?i->key.size():longest); + } + for (vector::iterator i = items.begin(); + i != items.end(); ++i) + { + i->longest = longest; + } +} +ostream &basic_io::operator<<(ostream &out, stanza const &st) +{ + for (vector::const_iterator i = st.items.begin(); + i != st.items.end(); ++i) + { + out << *i; + } + return out; +} +bool +stanza_reader::get(stanza &st) +{ + st.items.clear(); + while ((st.items.empty() && !last_read.key.empty()) || is >> last_read) + { + if (delims.find(last_read.key) == delims.end() || st.items.empty()) + st.items.push_back(last_read); + else + { + st.compute_longest(); + return true; + } + } + if (!is && !st.items.empty()) + { + st.compute_longest(); + return true; + } + return false; +} ============================================================ --- io.hh ccad8be31096e6ca11cae88425b5986ea258f07c +++ io.hh ccad8be31096e6ca11cae88425b5986ea258f07c @@ -0,0 +1,57 @@ +#ifndef __IO_HH_ +#define __IO_HH_ +// 2006-04-13 Timothy Brownawell +// +// The basic_io implementation in monotone represents basic_io as a +// token stream. This represents it as a data structure. +// Also, this allows i/o to/from iostreams, not just strings. + +#include +#include +#include +#include + +namespace basic_io { + using std::string; + using std::vector; + using std::istream; + using std::ostream; + using std::set; + struct value + { + string literal, parsed; + }; + istream &operator>>(istream &in, value &v); + ostream &operator<<(ostream &out, value &v); + struct item + { + string key; + vector values; + int longest; + }; + istream &operator>>(istream &in, item &i); + ostream &operator<<(ostream &out, item const &i); + + struct stanza + { + vector items; + void compute_longest(); + }; + ostream &operator<<(ostream &out, stanza const &st); + // There is no operator>>(istream, stanza), because that operation + // requires knowing what the stanza delimiters are. + // So we have a stanza_reader instead. + struct stanza_reader + { + istream &is; + set delims; + item last_read; + stanza_reader(istream &i, vector const &d) + : is(i), delims(d.begin(), d.end()) + { + } + bool get(stanza &st); + }; +} + +#endif