diff --git a/Makefile.am b/Makefile.am index 046e425317..be86bfa900 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,10 +34,8 @@ pyshared: mkdir pyshared mkdir pyshared/isc ln -s ${abs_top_srcdir}/src/lib/config/python/isc/config pyshared/isc/config - cat ${abs_top_srcdir}/src/lib/config/python/isc/__init__.py >> pyshared/isc/__init__.py ln -s ${abs_top_srcdir}/src/lib/cc/python/isc/cc pyshared/isc/cc ln -s ${abs_top_srcdir}/src/lib/cc/python/isc/cc pyshared/isc/Util - cat ${abs_top_srcdir}/src/lib/cc/python/isc/__init__.py >> pyshared/isc/__init__.py include: mkdir include diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 41e06e4ff9..3c6293f182 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1 +1 @@ -SUBDIRS = cc config dns auth +SUBDIRS = dns cc config auth diff --git a/src/lib/cc/cpp/Makefile.am b/src/lib/cc/cpp/Makefile.am index 87bbb57ec4..c69bf2880a 100644 --- a/src/lib/cc/cpp/Makefile.am +++ b/src/lib/cc/cpp/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/lib/cc/cpp -I$(top_srcdir)/ext -Wall -Werror +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext -Wall -Werror lib_LIBRARIES = libcc.a libcc_a_SOURCES = data.cc data.h session.cc session.h @@ -7,9 +7,10 @@ TESTS = if HAVE_GTEST TESTS += run_unittests run_unittests_SOURCES = data_unittests.cc run_unittests.cc -run_unittests_CPPFLAGS = $(GTEST_INCLUDES) -run_unittests_LDFLAGS = $(GTEST_LDFLAGS) +run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) run_unittests_LDADD = libcc.a $(GTEST_LDADD) +run_unittests_LDADD += $(top_builddir)/src/lib/dns/cpp/.libs/libdns.a endif noinst_PROGRAMS = $(TESTS) diff --git a/src/lib/cc/cpp/data.cc b/src/lib/cc/cpp/data.cc index f92afe1070..73f610fab1 100644 --- a/src/lib/cc/cpp/data.cc +++ b/src/lib/cc/cpp/data.cc @@ -1,5 +1,18 @@ -// XXXMLG UTF-8 and binary are all encoded as UTF-8, and decoded as UTF-8. -// XXXMLG This will cause issues down the road, but for today it works. +// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// $Id$ #include "data.h" @@ -29,15 +42,20 @@ const unsigned char ITEM_LENGTH_16 = 0x10; const unsigned char ITEM_LENGTH_8 = 0x20; const unsigned char ITEM_LENGTH_MASK = 0x30; -std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e) { - return out << e->str(); +static inline void +throwParseError(const std::string error, const std::string file, int line = 0, int pos = 0) +{ + if (line != 0 || pos != 0) { + std::stringstream ss; + ss << error << "in " + file + ":" << line << ":" << pos; + throw ParseError(ss.str()); + } else { + throw ParseError(error); + } } -const char* -ParseError::what() const throw() { - stringstream ss; - ss << msg << " line " << line << " pos " << pos; - return ss.str().c_str(); +std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e) { + return out << e->str(); } // @@ -106,7 +124,6 @@ Element::create(const std::map& m) // // helper functions for createFromString factory -// these should probably also be moved to member functions // static bool @@ -142,7 +159,8 @@ skip_chars(std::istream &in, const char *chars, int& line, int& pos) // // the character found is left on the stream static void -skip_to(std::istream &in, int& line, int& pos, const char* chars, const char* may_skip="") +skip_to(std::istream &in, const std::string& file, int& line, + int& pos, const char* chars, const char* may_skip="") { char c = in.get(); pos++; @@ -167,14 +185,14 @@ skip_to(std::istream &in, int& line, int& pos, const char* chars, const char* ma pos--; return; } else { - throw ParseError(std::string("'") + c + "' read, one of \"" + chars + "\" expected", line, pos); + throwParseError(std::string("'") + c + "' read, one of \"" + chars + "\" expected", file, line, pos); } } - throw ParseError(std::string("EOF read, one of \"") + chars + "\" expected", line, pos); + throwParseError(std::string("EOF read, one of \"") + chars + "\" expected", file, line, pos); } static std::string -str_from_stringstream(std::istream &in, int& line, int& pos) throw (ParseError) +str_from_stringstream(std::istream &in, const std::string& file, int& line, int& pos) throw (ParseError) { char c = 0; std::stringstream ss; @@ -184,7 +202,7 @@ str_from_stringstream(std::istream &in, int& line, int& pos) throw (ParseError) c = in.get(); pos++; } else { - throw ParseError("String expected", line, pos); + throwParseError("String expected", file, line, pos); } while (c != EOF && c != '"') { ss << c; @@ -249,7 +267,7 @@ from_stringstream_int_or_double(std::istream &in, int &line, int &pos) } static ElementPtr -from_stringstream_bool(std::istream &in, int& line, int& pos) +from_stringstream_bool(std::istream &in, const std::string& file, int& line, int& pos) { std::string word = word_from_stringstream(in, line, pos); if (boost::iequals(word, "True")) { @@ -257,18 +275,20 @@ from_stringstream_bool(std::istream &in, int& line, int& pos) } else if (boost::iequals(word, "False")) { return Element::create(false); } else { - throw ParseError(std::string("Bad boolean value: ") + word, line, pos); + throwParseError(std::string("Bad boolean value: ") + word, file, line, pos); + // above is a throw shortcur, return empty is never reached + return ElementPtr(); } } static ElementPtr -from_stringstream_string(std::istream &in, int& line, int& pos) +from_stringstream_string(std::istream &in, const std::string& file, int& line, int& pos) { - return Element::create(str_from_stringstream(in, line, pos)); + return Element::create(str_from_stringstream(in, file, line, pos)); } static ElementPtr -from_stringstream_list(std::istream &in, int& line, int& pos) +from_stringstream_list(std::istream &in, const std::string& file, int& line, int& pos) { char c = 0; std::vector v; @@ -277,9 +297,9 @@ from_stringstream_list(std::istream &in, int& line, int& pos) skip_chars(in, " \t\n", line, pos); while (c != EOF && c != ']') { if (in.peek() != ']') { - cur_list_element = Element::createFromString(in, line, pos); + cur_list_element = Element::createFromString(in, file, line, pos); v.push_back(cur_list_element); - skip_to(in, line, pos, ",]", " \t\n"); + skip_to(in, file, line, pos, ",]", " \t\n"); } c = in.get(); pos++; @@ -288,7 +308,7 @@ from_stringstream_list(std::istream &in, int& line, int& pos) } static ElementPtr -from_stringstream_map(std::istream &in, int& line, int& pos) +from_stringstream_map(std::istream &in, const std::string& file, int& line, int& pos) { char c = 0; std::map m; @@ -297,14 +317,14 @@ from_stringstream_map(std::istream &in, int& line, int& pos) ElementPtr cur_map_element; skip_chars(in, " \t\n", line, pos); while (c != EOF && c != '}') { - p.first = str_from_stringstream(in, line, pos); - skip_to(in, line, pos, ":", " \t\n"); + p.first = str_from_stringstream(in, file, line, pos); + skip_to(in, file, line, pos, ":", " \t\n"); // skip the : in.get(); pos++; - p.second = Element::createFromString(in, line, pos); + p.second = Element::createFromString(in, file, line, pos); m.insert(p); - skip_to(in, line, pos, ",}", " \t\n"); + skip_to(in, file, line, pos, ",}", " \t\n"); c = in.get(); pos++; } @@ -315,11 +335,11 @@ ElementPtr Element::createFromString(std::istream &in) throw(ParseError) { int line = 1, pos = 1; - return createFromString(in, line, pos); + return createFromString(in, "", line, pos); } ElementPtr -Element::createFromString(std::istream &in, int& line, int& pos) throw(ParseError) +Element::createFromString(std::istream &in, const std::string& file, int& line, int& pos) throw(ParseError) { char c = 0; ElementPtr element; @@ -348,26 +368,26 @@ Element::createFromString(std::istream &in, int& line, int& pos) throw(ParseErro case 'f': case 'F': in.putback(c); - element = from_stringstream_bool(in, line, pos); + element = from_stringstream_bool(in, file, line, pos); el_read = true; break; case '"': in.putback('"'); - element = from_stringstream_string(in, line, pos); + element = from_stringstream_string(in, file, line, pos); el_read = true; break; case '[': - element = from_stringstream_list(in, line, pos); + element = from_stringstream_list(in, file, line, pos); el_read = true; break; case '{': - element = from_stringstream_map(in, line, pos); + element = from_stringstream_map(in, file, line, pos); el_read = true; break; case EOF: break; default: - throw ParseError(std::string("error: unexpected character ") + c, line, pos); + throwParseError(std::string("error: unexpected character ") + c, file, line, pos); break; } } @@ -460,96 +480,6 @@ MapElement::str() return ss.str(); } -// -// helpers for strXML() functions -// - -// prefix with 'prefix' number of spaces -static void -pre(std::ostream &out, size_t prefix) -{ - for (size_t i = 0; i < prefix; i++) { - out << " "; - } -} - -std::string -IntElement::strXML(size_t prefix) -{ - std::stringstream ss; - pre(ss, prefix); - ss << str(); - return ss.str(); -} - -std::string -DoubleElement::strXML(size_t prefix) -{ - std::stringstream ss; - pre(ss, prefix); - ss << str(); - return ss.str(); -} - -std::string -BoolElement::strXML(size_t prefix) -{ - std::stringstream ss; - pre(ss, prefix); - ss << str(); - return ss.str(); -} - -std::string -StringElement::strXML(size_t prefix) -{ - std::stringstream ss; - pre(ss, prefix); - ss << stringValue(); - return ss.str(); -} - -std::string -ListElement::strXML(size_t prefix) -{ - std::stringstream ss; - std::vector v; - pre(ss, prefix); - ss << "" << endl;; - v = listValue(); - for (std::vector::iterator it = v.begin(); it != v.end(); ++it) { - pre(ss, prefix + 4); - ss << "" << endl; - ss << (*it)->strXML(prefix + 8) << endl; - pre(ss, prefix + 4); - ss << "" << endl; - } - pre(ss, prefix); - ss << ""; - return ss.str(); -} - -std::string -MapElement::strXML(size_t prefix) -{ - std::stringstream ss; - std::map m; - m = mapValue(); - pre(ss, prefix); - ss << "" << endl; - for (std::map::iterator it = m.begin(); it != m.end(); ++it) { - pre(ss, prefix + 4); - ss << "" << endl; - pre(ss, prefix); - ss << (*it).second->strXML(prefix+8) << endl; - pre(ss, prefix + 4); - ss << "" << endl; - } - pre(ss, prefix); - ss << ""; - return ss.str(); -} - // throws when one of the types in the path (except the one // we're looking for) is not a MapElement // returns 0 if it could simply not be found @@ -824,33 +754,33 @@ encode_length(unsigned int length, unsigned char type) } std::string -StringElement::toWire(int omit_length) +Element::toWire(int omit_length) { std::stringstream ss; - - unsigned int length = stringValue().length(); - ss << encode_length(length, ITEM_UTF8) << stringValue(); - + toWire(ss, omit_length); return ss.str(); } -std::string -IntElement::toWire(int omit_length) +void +StringElement::toWire(std::stringstream& ss, int omit_length) +{ + unsigned int length = stringValue().length(); + ss << encode_length(length, ITEM_UTF8) << stringValue(); +} + +void +IntElement::toWire(std::stringstream& ss, int omit_length) { - std::stringstream ss; std::stringstream text; text << str(); int length = text.str().length(); ss << encode_length(length, ITEM_INT) << text.str(); - - return ss.str(); } -std::string -BoolElement::toWire(int omit_length) +void +BoolElement::toWire(std::stringstream& ss, int omit_length) { - std::stringstream ss; std::stringstream text; text << str(); @@ -861,87 +791,80 @@ BoolElement::toWire(int omit_length) } else { ss << 0x00; } - - return ss.str(); } -std::string -DoubleElement::toWire(int omit_length) +void +DoubleElement::toWire(std::stringstream& ss, int omit_length) { - std::stringstream ss; std::stringstream text; text << str(); int length = text.str().length(); ss << encode_length(length, ITEM_REAL) << text.str(); - - return ss.str(); } -std::string -ListElement::toWire(int omit_length) +void +ListElement::toWire(std::stringstream& ss, int omit_length) { - std::stringstream ss; + std::stringstream ss2; std::vector v; v = listValue(); for (std::vector::iterator it = v.begin() ; it != v.end() ; ++it) { - ss << (*it)->toWire(0); + (*it)->toWire(ss2, 0); } if (omit_length) { - return ss.str(); + ss << ss2.rdbuf(); } else { - std::stringstream ss_len; - ss_len << encode_length(ss.str().length(), ITEM_LIST); - ss_len << ss.str(); - return ss_len.str(); + stringbuf *ss2_buf = ss2.rdbuf(); + ss2_buf->pubseekpos(0); + ss << encode_length(ss2_buf->in_avail(), ITEM_LIST); + ss << ss2_buf; } } -std::string -encode_tag(const std::string &s) +void +encode_tag(std::stringstream& ss, const std::string &s) { - std::stringstream ss; int length = s.length(); unsigned char val = length & 0x000000ff; ss << val << s; - - return ss.str(); } -std::string -MapElement::toWire(int omit_length) +void +MapElement::toWire(std::stringstream& ss, int omit_length) { - std::stringstream ss; + std::stringstream ss2; std::map m; // // If we don't want the length, we will want the protocol header // if (omit_length) { - ss << PROTOCOL_VERSION[0] << PROTOCOL_VERSION[1]; - ss << PROTOCOL_VERSION[2] << PROTOCOL_VERSION[3]; + ss2 << PROTOCOL_VERSION[0] << PROTOCOL_VERSION[1]; + ss2 << PROTOCOL_VERSION[2] << PROTOCOL_VERSION[3]; } m = mapValue(); for (std::map::iterator it = m.begin() ; it != m.end() ; ++it) { - ss << encode_tag((*it).first); - ss << (*it).second->toWire(0); + encode_tag(ss2, (*it).first); + (*it).second->toWire(ss2, 0); } // // add length if needed // if (omit_length) { - return ss.str(); + ss << ss2.rdbuf(); } else { - std::stringstream ss_len; - ss_len << encode_length(ss.str().length(), ITEM_HASH); - ss_len << ss.str(); - return ss_len.str(); + + stringbuf *ss2_buf = ss2.rdbuf(); + ss2_buf->pubseekpos(0); + ss << encode_length(ss2_buf->in_avail(), ITEM_HASH); + ss << ss2_buf; } } diff --git a/src/lib/cc/cpp/data.h b/src/lib/cc/cpp/data.h index c01eb42edc..04058a5e21 100644 --- a/src/lib/cc/cpp/data.h +++ b/src/lib/cc/cpp/data.h @@ -1,4 +1,4 @@ -// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above @@ -22,6 +22,7 @@ #include #include #include +#include namespace isc { namespace data { @@ -35,28 +36,22 @@ typedef boost::shared_ptr ElementPtr; /// ListElement) /// // todo: include types and called function in the exception -class TypeError : public std::exception { +class TypeError : public isc::dns::Exception { public: - TypeError(std::string m = "Attempt to use function on wrong Element type") : msg(m) {} - ~TypeError() throw() {} - const char* what() const throw() { return msg.c_str(); } -private: - std::string msg; + TypeError(const char* file, size_t line, const char* what) : + isc::dns::Exception(file, line, what) {} }; /// /// \brief A standard Data module exception that is thrown if a parse /// error is encountered when constructing an Element from a string /// -class ParseError : public std::exception { +// i'd like to use Exception here but we need one that is derived from +// runtime_error (as this one is directly based on external data, and +// i want to add some values to any static data string that is provided) +class ParseError : public std::runtime_error { public: - ParseError(std::string m = "Parse error in element data", int l = 0, int p = 0) : msg(m), line(l), pos(p) {} - ~ParseError() throw() {} - const char* what() const throw(); -private: - std::string msg; - int line; - int pos; + ParseError(const std::string &err) : std::runtime_error(err) {}; }; /// @@ -120,22 +115,14 @@ public: /// \return std::string containing the string representation virtual std::string str() = 0; - /// Returns an xml representation for the Element and all its - /// child elements - /// - /// \param prefix Every line of the xml string will be prefixed with - /// the number of spaces specified here - /// \return std::string containing the xml representation - // todo - virtual std::string strXML(size_t prefix = 0) = 0; - /// Returns the wireformat for the Element and all its child /// elements. /// /// \param omit_length If this is non-zero, the item length will /// be omitted from the wire format /// \return std::string containing the element in wire format - virtual std::string toWire(int omit_length = 1) = 0; + std::string toWire(int omit_length = 1); + virtual void toWire(std::stringstream& out, int omit_length = 1) = 0; /// \name Type-specific getters /// @@ -146,12 +133,12 @@ public: /// If you want an exception-safe getter method, use /// getValue() below //@{ - virtual int intValue() { throw TypeError(); }; - virtual double doubleValue() { throw TypeError(); }; - virtual bool boolValue() { throw TypeError(); }; - virtual std::string stringValue() { throw TypeError(); }; - virtual const std::vector >& listValue() { throw TypeError(); }; // replace with real exception or empty vector? - virtual const std::map >& mapValue() { throw TypeError(); }; // replace with real exception or empty map? + virtual int intValue() { dns_throw(TypeError, "intValue() called on non-integer Element"); }; + virtual double doubleValue() { dns_throw(TypeError, "doubleValue() called on non-double Element"); }; + virtual bool boolValue() { dns_throw(TypeError, "boolValue() called on non-Bool Element"); }; + virtual std::string stringValue() { dns_throw(TypeError, "stringValue() called on non-string Element"); }; + virtual const std::vector >& listValue() { dns_throw(TypeError, "listValue() called on non-list Element"); }; // replace with real exception or empty vector? + virtual const std::map >& mapValue() { dns_throw(TypeError, "mapValue() called on non-map Element"); }; // replace with real exception or empty map? //@} /// \name Exception-safe getters @@ -198,21 +185,21 @@ public: /// Returns the ElementPtr at the given index. If the index is out /// of bounds, this function throws an std::out_of_range exception. /// \param i The position of the ElementPtr to return - virtual ElementPtr get(const int i) { throw TypeError(); }; + virtual ElementPtr get(const int i) { dns_throw(TypeError, "get(int) called on a non-list Element"); }; /// Sets the ElementPtr at the given index. If the index is out /// of bounds, this function throws an std::out_of_range exception. /// \param i The position of the ElementPtr to set /// \param element The ElementPtr to set at the position - virtual void set(const size_t i, ElementPtr element) { throw TypeError(); }; + virtual void set(const size_t i, ElementPtr element) { dns_throw(TypeError, "set(int, element) called on a non-list Element"); }; /// Adds an ElementPtr to the list /// \param element The ElementPtr to add - virtual void add(ElementPtr element) { throw TypeError(); }; + virtual void add(ElementPtr element) { dns_throw(TypeError, "add() called on a non-list Element"); }; /// Removes the element at the given position. If the index is out /// of nothing happens. /// \param i The index of the element to remove. - virtual void remove(const int i) { throw TypeError(); }; + virtual void remove(const int i) { dns_throw(TypeError, "remove(int) called on a non-list Element"); }; /// Returns the number of elements in the list. - virtual size_t size() { throw TypeError(); }; + virtual size_t size() { dns_throw(TypeError, "size() called on a non-list Element"); }; //@} /// \name MapElement functions @@ -223,17 +210,17 @@ public: /// Returns the ElementPtr at the given key /// \param name The key of the Element to return /// \return The ElementPtr at the given key - virtual ElementPtr get(const std::string& name) { throw TypeError(); } ; + virtual ElementPtr get(const std::string& name) { dns_throw(TypeError, "get(string) called on a non-map Element"); } ; /// Sets the ElementPtr at the given key /// \param name The key of the Element to set - virtual void set(const std::string& name, ElementPtr element) { throw TypeError(); }; + virtual void set(const std::string& name, ElementPtr element) { dns_throw(TypeError, "set(name, element) called on a non-map Element"); }; /// Remove the ElementPtr at the given key /// \param name The key of the Element to remove - virtual void remove(const std::string& name) { throw TypeError(); }; + virtual void remove(const std::string& name) { dns_throw(TypeError, "remove(string) called on a non-map Element"); }; /// Checks if there is data at the given key /// \param name The key of the Element to remove /// \return true if there is data at the key, false if not. - virtual bool contains(const std::string& name) { throw TypeError(); } + virtual bool contains(const std::string& name) { dns_throw(TypeError, "contains(string) called on a non-map Element"); } /// Recursively finds any data at the given identifier. The /// identifier is a /-separated list of names of nested maps, with /// the last name being the leaf that is returned. @@ -247,7 +234,7 @@ public: /// \return The ElementPtr at the given identifier. Returns a /// null ElementPtr if it is not found, which can be checked with /// Element::is_null(ElementPtr e). - virtual ElementPtr find(const std::string& identifier) { throw TypeError(); }; + virtual ElementPtr find(const std::string& identifier) { dns_throw(TypeError, "find(string) called on a non-map Element"); }; /// See \c Element::find() /// \param identifier The identifier of the element to find /// \param t Reference to store the resulting ElementPtr, if found. @@ -308,9 +295,8 @@ public: /// \return An ElementPtr that contains the element(s) specified /// in the given input stream. // make this one private? - static ElementPtr createFromString(std::istream& in, int& line, int &pos) throw(ParseError); + static ElementPtr createFromString(std::istream& in, const std::string& file, int& line, int &pos) throw(ParseError); //@} - //static ElementPtr create_from_xml(std::stringstream& in); /// \name Wire format factory functions @@ -341,8 +327,7 @@ public: bool getValue(int& t) { t = i; return true; }; bool setValue(const int v) { i = v; return true; }; std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); }; class DoubleElement : public Element { @@ -354,8 +339,7 @@ public: bool getValue(double& t) { t = d; return true; }; bool setValue(const double v) { d = v; return true; }; std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); }; class BoolElement : public Element { @@ -367,8 +351,7 @@ public: bool getValue(bool& t) { t = b; return true; }; bool setValue(const bool v) { b = v; return true; }; std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); }; class StringElement : public Element { @@ -380,8 +363,7 @@ public: bool getValue(std::string& t) { t = s; return true; }; bool setValue(const std::string& v) { s = v; return true; }; std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); }; class ListElement : public Element { @@ -397,8 +379,7 @@ public: void add(ElementPtr e) { l.push_back(e); }; void remove(int i) { l.erase(l.begin() + i); }; std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); size_t size() { return l.size(); } }; @@ -415,8 +396,7 @@ public: void remove(const std::string& s) { m.erase(s); } bool contains(const std::string& s) { return m.find(s) != m.end(); } std::string str(); - std::string strXML(size_t prefix = 0); - std::string toWire(int omit_length = 1); + void toWire(std::stringstream& ss, int omit_length = 1); // // Encode into the CC wire format.