Browse Source

Data Elements fixups;
- isc::data::TypeError is now a subtype of isc::dns::Exception (which i think we should move to namespace isc::)
- isc::data::ParseError not yet; it is a subclass of std::runtime_error (due to the error in quiestion being constructed on the fly, can we add an equivalent of that to isc::[dns::]Exception?
- toWire() family of functions now writes directly to a stream, with a convenience function for Element that does return a std::string
- removed unused and unspecified toXML functions


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@699 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
c51d6c7ba3
5 changed files with 131 additions and 229 deletions
  1. 0 2
      Makefile.am
  2. 1 1
      src/lib/Makefile.am
  3. 4 3
      src/lib/cc/cpp/Makefile.am
  4. 91 168
      src/lib/cc/cpp/data.cc
  5. 35 55
      src/lib/cc/cpp/data.h

+ 0 - 2
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

+ 1 - 1
src/lib/Makefile.am

@@ -1 +1 @@
-SUBDIRS = cc config dns auth
+SUBDIRS = dns cc config auth

+ 4 - 3
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)

+ 91 - 168
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<std::string, ElementPtr>& 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<ElementPtr> 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<std::string, ElementPtr> 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, "<unknown>", 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<ElementPtr> v;
-    pre(ss, prefix);
-    ss << "<list>" << endl;;
-    v = listValue();
-    for (std::vector<ElementPtr>::iterator it = v.begin(); it != v.end(); ++it) {
-        pre(ss, prefix + 4);
-        ss << "<listitem>" << endl;
-        ss << (*it)->strXML(prefix + 8) << endl;
-        pre(ss, prefix + 4);
-        ss << "</listitem>" << endl;
-    }
-    pre(ss, prefix);
-    ss << "</list>";
-    return ss.str();
-}
-
-std::string
-MapElement::strXML(size_t prefix)
-{
-    std::stringstream ss;
-    std::map<std::string, ElementPtr> m;
-    m = mapValue();
-    pre(ss, prefix);
-    ss << "<map>" << endl;
-    for (std::map<std::string, ElementPtr>::iterator it = m.begin(); it != m.end(); ++it) {
-        pre(ss, prefix + 4);
-        ss << "<mapitem name=\"" << (*it).first << "\">" << endl;
-        pre(ss, prefix);
-        ss << (*it).second->strXML(prefix+8) << endl;
-        pre(ss, prefix + 4);
-        ss << "</mapitem>" << endl;
-    }
-    pre(ss, prefix);
-    ss << "</map>";
-    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;
+    toWire(ss, omit_length);
+    return ss.str();
+}
 
+void
+StringElement::toWire(std::stringstream& ss, int omit_length)
+{
     unsigned int length = stringValue().length();
     ss << encode_length(length, ITEM_UTF8) << stringValue();
-
-    return ss.str();
 }
 
-std::string
-IntElement::toWire(int omit_length)
+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<ElementPtr> v;
     v = listValue();
     for (std::vector<ElementPtr>::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<std::string, ElementPtr> 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<std::string, ElementPtr>::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;
     }
 }
 

+ 35 - 55
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 <map>
 #include <boost/shared_ptr.hpp>
 #include <stdexcept>
+#include <dns/cpp/exceptions.h>
 
 namespace isc { namespace data {
 
@@ -35,28 +36,22 @@ typedef boost::shared_ptr<Element> 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<boost::shared_ptr<Element> >& listValue() { throw TypeError(); }; // replace with real exception or empty vector?
-    virtual const std::map<std::string, boost::shared_ptr<Element> >& 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<boost::shared_ptr<Element> >& listValue() { dns_throw(TypeError, "listValue() called on non-list Element"); }; // replace with real exception or empty vector?
+    virtual const std::map<std::string, boost::shared_ptr<Element> >& 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.