#
#
# 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