[svn] commit: r290 - in /branches/jelte-datadef/src/lib/cc/cpp: data.cc data.h
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Nov 4 13:41:13 UTC 2009
Author: jelte
Date: Wed Nov 4 13:41:12 2009
New Revision: 290
Log:
create_from_string now throws a ParseError exception instead of returning an empty shared pointer
keep track of position when parsing a string, for better error feedback, for example when using files
Modified:
branches/jelte-datadef/src/lib/cc/cpp/data.cc
branches/jelte-datadef/src/lib/cc/cpp/data.h
Modified: branches/jelte-datadef/src/lib/cc/cpp/data.cc
==============================================================================
--- branches/jelte-datadef/src/lib/cc/cpp/data.cc (original)
+++ branches/jelte-datadef/src/lib/cc/cpp/data.cc Wed Nov 4 13:41:12 2009
@@ -27,6 +27,13 @@
return out << e->str();
}
+const char*
+ParseError::what() const throw() {
+ stringstream ss;
+ ss << msg << " line " << line << " pos " << pos;
+ return ss.str().c_str();
+}
+
//
// factory functions
//
@@ -64,7 +71,6 @@
Element::create(const bool b)
{
try {
- cout << "creating boolelement" << endl;
return ElementPtr(new BoolElement(b));
} catch (std::bad_alloc) {
return ElementPtr();
@@ -109,83 +115,113 @@
}
static void
-skip_chars(std::stringstream &in, const char *chars)
+skip_chars(std::istream &in, const char *chars, int& line, int& pos)
{
char c = in.peek();
while (char_in(c, chars) && c != EOF) {
+ if (c == '\n') {
+ line++;
+ pos = 1;
+ } else {
+ pos++;
+ }
in.get();
c = in.peek();
}
}
+/*static void
+skip_chars(std::istream &in, const char *chars)
+{
+ int l = 0, p = 0;
+ skip_chars(in, chars, l, p);
+}*/
// skip on the input stream to one of the characters in chars
// if another character is found this function returns false
// unles that character is specified in the optional may_skip
//
// the character found is left on the stream
-static bool
-skip_to(std::stringstream &in, const char *chars, const char *may_skip="")
+static void
+skip_to(std::istream &in, int& line, int& pos, const char* chars, const char* may_skip="")
{
char c = in.get();
+ pos++;
while (c != EOF) {
+ if (c == '\n') {
+ pos = 1;
+ line++;
+ }
if (char_in(c, may_skip)) {
c = in.get();
+ pos++;
} else if (char_in(c, chars)) {
while(char_in(in.peek(), may_skip)) {
+ if (in.peek() == '\n') {
+ pos = 1;
+ line++;
+ }
in.get();
+ pos++;
}
in.putback(c);
- return true;
+ pos--;
+ return;
} else {
- // TODO: provide feeback mechanism?
- cout << "error, '" << c << "' read; one of \"" << chars << "\" expected" << endl;
- in.putback(c);
- return false;
- }
- }
- // TODO: provide feeback mechanism?
- cout << "error, EOF read; one of \"" << chars << "\" expected" << endl;
- in.putback(c);
- return false;
-}
+ throw ParseError(std::string("'") + c + "' read, one of \"" + chars + "\" expected", line, pos);
+ }
+ }
+ throw ParseError(std::string("EOF read, one of \"") + chars + "\" expected", line, pos);
+}
+
+/*static bool
+skip_to(std::istream &in, const char *chars, const char *may_skip="") {
+ int line = 0, pos = 0;
+ return skip_to(in, line, pos, chars, may_skip);
+}*/
static std::string
-str_from_stringstream(std::stringstream &in)
+str_from_stringstream(std::istream &in, int& line, int& pos) throw (ParseError)
{
char c = 0;
std::stringstream ss;
c = in.get();
+ pos++;
if (c == '"') {
c = in.get();
+ pos++;
} else {
- return "badstring";
+ throw ParseError("String expected", line, pos);
}
while (c != EOF && c != '"') {
ss << c;
if (c == '\\' && in.peek() == '"') {
ss << in.get();
+ pos++;
}
c = in.get();
+ pos++;
}
return ss.str();
}
static std::string
-word_from_stringstream(std::stringstream &in)
+word_from_stringstream(std::istream &in, int& line, int& pos)
{
std::stringstream ss;
while (isalpha(in.peek())) {
ss << (char) in.get();
}
+ pos += ss.str().size();
return ss.str();
}
static ElementPtr
-from_stringstream_int_or_double(std::stringstream &in)
+from_stringstream_int_or_double(std::istream &in, int &line, int &pos)
{
int i;
in >> i;
+ // TODO count pos
if (in.peek() == '.') {
double d;
in >> d;
@@ -197,9 +233,9 @@
}
static ElementPtr
-from_stringstream_bool(std::stringstream &in)
-{
- std::string word = word_from_stringstream(in);
+from_stringstream_bool(std::istream &in, int& line, int& pos)
+{
+ std::string word = word_from_stringstream(in, line, pos);
if (boost::iequals(word, "True")) {
return Element::create(true);
} else if (boost::iequals(word, "False")) {
@@ -210,65 +246,78 @@
}
static ElementPtr
-from_stringstream_string(std::stringstream &in)
-{
- return Element::create(str_from_stringstream(in));
+from_stringstream_string(std::istream &in, int& line, int& pos)
+{
+ return Element::create(str_from_stringstream(in, line, pos));
}
static ElementPtr
-from_stringstream_list(std::stringstream &in)
+from_stringstream_list(std::istream &in, int& line, int& pos)
{
char c = 0;
std::vector<ElementPtr> v;
ElementPtr cur_list_element;
-
- skip_chars(in, " \t\n");
+ //cout << "reading list at line " << line << " pos " << pos << endl;
+
+ skip_chars(in, " \t\n", line, pos);
while (c != EOF && c != ']') {
- cur_list_element = Element::create_from_string(in);
- v.push_back(cur_list_element);
- if (!skip_to(in, ",]", " \t\n")) {
- return ElementPtr();
+ //cout << "at line " << line << " pos " << pos << " cur c: " << c << " next c: " << char(in.peek()) << endl;
+ if (in.peek() != ']') {
+ cur_list_element = Element::create_from_string(in, line, pos);
+ v.push_back(cur_list_element);
+ skip_to(in, line, pos, ",]", " \t\n");
}
c = in.get();
+ pos++;
}
return Element::create(v);
}
static ElementPtr
-from_stringstream_map(std::stringstream &in)
+from_stringstream_map(std::istream &in, int& line, int& pos)
{
char c = 0;
std::map<std::string, ElementPtr> m;
std::pair<std::string, ElementPtr> p;
std::string cur_map_key;
ElementPtr cur_map_element;
- skip_chars(in, " \t\n");
+ skip_chars(in, " \t\n", line, pos);
while (c != EOF && c != '}') {
- p.first = str_from_stringstream(in);
- if (!skip_to(in, ":", " \t\n")) {
- return ElementPtr();
- } else {
- // skip the :
- in.get();
- }
- p.second = Element::create_from_string(in);
+ p.first = str_from_stringstream(in, line, pos);
+ skip_to(in, line, pos, ":", " \t\n");
+ // skip the :
+ in.get();
+ pos++;
+ p.second = Element::create_from_string(in, line, pos);
if (!p.second) { return ElementPtr(); };
m.insert(p);
- skip_to(in, ",}", " \t\n");
+ skip_to(in, line, pos, ",}", " \t\n");
c = in.get();
+ pos++;
}
return Element::create(m);
}
-ElementPtr
-Element::create_from_string(std::stringstream &in)
+//ElementPtr
+//Element::create_from_string(std::stringstream &in)
+ElementPtr
+Element::create_from_string(std::istream &in) throw(ParseError)
+{
+ int line = 1, pos = 1;
+ return create_from_string(in, line, pos);
+}
+
+ElementPtr
+Element::create_from_string(std::istream &in, int& line, int& pos) throw(ParseError)
{
char c = 0;
ElementPtr element;
bool el_read = false;
- skip_chars(in, " \n\t");
+ skip_chars(in, " \n\t", line, pos);
while (c != EOF && !el_read) {
c = in.get();
+ pos++;
+ //std::cout << c << std::endl;
switch(c) {
case '1':
case '2':
@@ -281,7 +330,7 @@
case '9':
case '0':
in.putback(c);
- element = from_stringstream_int_or_double(in);
+ element = from_stringstream_int_or_double(in, line, pos);
el_read = true;
break;
case 't':
@@ -289,27 +338,26 @@
case 'f':
case 'F':
in.putback(c);
- element = from_stringstream_bool(in);
+ element = from_stringstream_bool(in, line, pos);
el_read = true;
break;
case '"':
in.putback('"');
- element = from_stringstream_string(in);
+ element = from_stringstream_string(in, line, pos);
el_read = true;
break;
case '[':
- element = from_stringstream_list(in);
+ element = from_stringstream_list(in, line, pos);
el_read = true;
break;
case '{':
- element = from_stringstream_map(in);
+ element = from_stringstream_map(in, line, pos);
el_read = true;
break;
+ case EOF:
+ break;
default:
- // TODO this might not be a fatal error
- // provide feedback mechanism?
- cout << "error: unexpected '" << c << "'" << endl;
- return ElementPtr();
+ throw ParseError(std::string("error: unexpected character ") + c, line, pos);
break;
}
}
@@ -317,7 +365,7 @@
return element;
} else {
// throw exception?
- return ElementPtr();
+ throw ParseError("nothing read");
}
}
Modified: branches/jelte-datadef/src/lib/cc/cpp/data.h
==============================================================================
--- branches/jelte-datadef/src/lib/cc/cpp/data.h (original)
+++ branches/jelte-datadef/src/lib/cc/cpp/data.h Wed Nov 4 13:41:12 2009
@@ -18,6 +18,17 @@
const char* what() const throw() { return msg.c_str(); }
private:
std::string msg;
+ };
+
+ class ParseError : public std::exception {
+ 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;
};
class DecodeError : public std::exception {
@@ -145,8 +156,11 @@
// the memory could not be allocated
// example:
// ElementPtr my_element = Element::create_from_string("{\"foo\": [ 1, 2, false ] }");
- static ElementPtr create_from_string(std::stringstream& in);
+ //static ElementPtr create_from_string(std::stringstream& in);
static ElementPtr create_from_string(const std::string& in);
+ static ElementPtr create_from_string(std::istream& in) throw(ParseError);
+ // make this one private?
+ static ElementPtr create_from_string(std::istream& in, int& line, int &pos) throw(ParseError);
//static ElementPtr create_from_xml(std::stringstream& in);
More information about the bind10-changes
mailing list