diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-11-17 01:21:00 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-11-17 01:21:00 -0800 |
commit | 08cf048f2a8ed0fa096f2c82e147b61ffc480e2a (patch) | |
tree | 80493ca241c9172e21df76cedb98312af6de8113 | |
parent | 21c277062ef151ad86e2003ad0e2bfb09f3d4c2d (diff) | |
download | mu-08cf048f2a8ed0fa096f2c82e147b61ffc480e2a.tar.gz |
2454
Another gotcha uncovered in the process of sorting out the previous commit: I keep using eof() but forgetting that there are two other states an istream can get into. Just never use eof().
-rw-r--r-- | 001help.cc | 7 | ||||
-rw-r--r-- | 010vm.cc | 6 | ||||
-rw-r--r-- | 011load.cc | 26 | ||||
-rw-r--r-- | 014literal_string.cc | 10 | ||||
-rw-r--r-- | 030container.cc | 4 | ||||
-rw-r--r-- | 050scenario.cc | 2 | ||||
-rw-r--r-- | 054dilated_reagent.cc | 2 | ||||
-rw-r--r-- | 055parse_tree.cc | 4 | ||||
-rw-r--r-- | 058shape_shifting_container.cc | 2 | ||||
-rw-r--r-- | 092persist.cc | 2 |
10 files changed, 36 insertions, 29 deletions
diff --git a/001help.cc b/001help.cc index c193cf7d..4b7c3858 100644 --- a/001help.cc +++ b/001help.cc @@ -113,6 +113,13 @@ template<typename T> typename T::mapped_type& get_or_insert(T& map, typename T:: } //: The contract: any container that relies on get_or_insert should never call //: contains_key. +//: +//: 7. istreams are a royal pain in the arse. You have to be careful about +//: what subclass you try to putback into. You have to watch out for the pesky +//: failbit and badbit. Just avoid eof() and use this helper instead. +bool has_data(istream& in) { + return in && !in.eof(); +} :(before "End Includes") #include<assert.h> diff --git a/010vm.cc b/010vm.cc index 016d3ad6..fcd72be2 100644 --- a/010vm.cc +++ b/010vm.cc @@ -236,7 +236,7 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false), ty istringstream in(s); in >> std::noskipws; // properties - while (!in.eof()) { + while (has_data(in)) { istringstream row(slurp_until(in, '/')); row >> std::noskipws; string key = slurp_until(row, ':'); @@ -261,7 +261,7 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false), ty string_tree* parse_property_list(istream& in) { skip_whitespace(in); - if (in.eof()) return NULL; + if (!has_data(in)) return NULL; string_tree* result = new string_tree(slurp_until(in, ':')); result->right = parse_property_list(in); return result; @@ -539,7 +539,7 @@ void dump(const string_tree* x, ostream& out) { } void skip_whitespace(istream& in) { - while (!in.eof() && isspace(in.peek()) && in.peek() != '\n') { + while (in && isspace(in.peek()) && in.peek() != '\n') { in.get(); } } diff --git a/011load.cc b/011load.cc index b318e88a..578e2b46 100644 --- a/011load.cc +++ b/011load.cc @@ -19,9 +19,9 @@ vector<recipe_ordinal> load(string form) { vector<recipe_ordinal> load(istream& in) { in >> std::noskipws; vector<recipe_ordinal> result; - while (!in.eof()) { + while (has_data(in)) { skip_whitespace_and_comments(in); - if (in.eof()) break; + if (!has_data(in)) break; string command = next_word(in); // Command Handlers if (command == "recipe") { @@ -82,25 +82,25 @@ void slurp_body(istream& in, recipe& result) { bool next_instruction(istream& in, instruction* curr) { curr->clear(); - if (in.eof()) { + if (!has_data(in)) { raise_error << "0: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace(in); - if (in.eof()) { + if (!has_data(in)) { raise_error << "1: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace_and_comments(in); - if (in.eof()) { + if (!has_data(in)) { raise_error << "2: unbalanced '[' for recipe\n" << end(); return false; } vector<string> words; - while (in.peek() != '\n' && !in.eof()) { + while (has_data(in) && in.peek() != '\n') { skip_whitespace(in); - if (in.eof()) { + if (!has_data(in)) { raise_error << "3: unbalanced '[' for recipe\n" << end(); return false; } @@ -117,7 +117,7 @@ bool next_instruction(istream& in, instruction* curr) { curr->is_label = true; curr->label = words.at(0); trace(9993, "parse") << "label: " << curr->label << end(); - if (in.eof()) { + if (!has_data(in)) { raise_error << "7: unbalanced '[' for recipe\n" << end(); return false; } @@ -151,7 +151,7 @@ bool next_instruction(istream& in, instruction* curr) { for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) { trace(9993, "parse") << " product: " << p->to_string() << end(); } - if (in.eof()) { + if (!has_data(in)) { raise_error << "9: unbalanced '[' for recipe\n" << end(); return false; } @@ -176,7 +176,7 @@ string Ignore(","); // meaningless except within [] strings :(code) void slurp_word(istream& in, ostream& out) { char c; - if (!in.eof() && Terminators.find(in.peek()) != string::npos) { + if (has_data(in) && Terminators.find(in.peek()) != string::npos) { in >> c; out << c; return; @@ -198,7 +198,7 @@ void skip_ignored_characters(istream& in) { void skip_whitespace_and_comments(istream& in) { while (true) { - if (in.eof()) break; + if (!has_data(in)) break; if (isspace(in.peek())) in.get(); else if (in.peek() == ',') in.get(); else if (in.peek() == '#') skip_comment(in); @@ -207,9 +207,9 @@ void skip_whitespace_and_comments(istream& in) { } void skip_comment(istream& in) { - if (!in.eof() && in.peek() == '#') { + if (has_data(in) && in.peek() == '#') { in.get(); - while (!in.eof() && in.peek() != '\n') in.get(); + while (has_data(in) && in.peek() != '\n') in.get(); } } diff --git a/014literal_string.cc b/014literal_string.cc index 1e7f7b0b..34655aa9 100644 --- a/014literal_string.cc +++ b/014literal_string.cc @@ -32,7 +32,7 @@ if (in.peek() == '[') { :(code) string slurp_quoted(istream& in) { ostringstream out; - assert(!in.eof()); assert(in.peek() == '['); out << static_cast<char>(in.get()); // slurp the '[' + assert(has_data(in)); assert(in.peek() == '['); out << static_cast<char>(in.get()); // slurp the '[' if (is_code_string(in, out)) slurp_quoted_comment_aware(in, out); else @@ -43,7 +43,7 @@ string slurp_quoted(istream& in) { // A string is a code string if it contains a newline before any non-whitespace // todo: support comments before the newline. But that gets messy. bool is_code_string(istream& in, ostream& out) { - while (!in.eof()) { + while (has_data(in)) { char c = in.get(); if (!isspace(c)) { in.putback(c); @@ -61,7 +61,7 @@ bool is_code_string(istream& in, ostream& out) { // strings. void slurp_quoted_comment_oblivious(istream& in, ostream& out) { int brace_depth = 1; - while (!in.eof()) { + while (has_data(in)) { char c = in.get(); if (c == '\\') { out << static_cast<char>(in.get()); @@ -72,7 +72,7 @@ void slurp_quoted_comment_oblivious(istream& in, ostream& out) { if (c == ']') --brace_depth; if (brace_depth == 0) break; } - if (in.eof() && brace_depth > 0) { + if (!has_data(in) && brace_depth > 0) { raise_error << "unbalanced '['\n" << end(); out.clear(); } @@ -88,7 +88,7 @@ void slurp_quoted_comment_aware(istream& in, ostream& out) { } if (c == '#') { out << c; - while (!in.eof() && in.peek() != '\n') out << static_cast<char>(in.get()); + while (has_data(in) && in.peek() != '\n') out << static_cast<char>(in.get()); continue; } if (c == '[') { diff --git a/030container.cc b/030container.cc index 25303f39..9be42f23 100644 --- a/030container.cc +++ b/030container.cc @@ -415,7 +415,7 @@ void insert_container(const string& command, kind_of_type kind, istream& in) { recently_added_types.push_back(get(Type_ordinal, name)); info.name = name; info.kind = kind; - while (!in.eof()) { + while (has_data(in)) { skip_whitespace_and_comments(in); string element = next_word(in); if (element == "]") break; @@ -424,7 +424,7 @@ void insert_container(const string& command, kind_of_type kind, istream& in) { info.element_names.push_back(slurp_until(inner, ':')); trace(9993, "parse") << " element name: " << info.element_names.back() << end(); type_tree* new_type = NULL; - for (type_tree** curr_type = &new_type; !inner.eof(); curr_type = &(*curr_type)->right) { + for (type_tree** curr_type = &new_type; has_data(inner); curr_type = &(*curr_type)->right) { string type_name = slurp_until(inner, ':'); // End insert_container Special Uses(type_name) if (!contains_key(Type_ordinal, type_name) diff --git a/050scenario.cc b/050scenario.cc index 0a1c0f90..71dfa72d 100644 --- a/050scenario.cc +++ b/050scenario.cc @@ -270,7 +270,7 @@ void check_memory(const string& s) { set<long long int> locations_checked; while (true) { skip_whitespace_and_comments(in); - if (in.eof()) break; + if (!has_data(in)) break; string lhs = next_word(in); if (!is_integer(lhs)) { check_type(lhs, in); diff --git a/054dilated_reagent.cc b/054dilated_reagent.cc index f1d3b267..ac40f049 100644 --- a/054dilated_reagent.cc +++ b/054dilated_reagent.cc @@ -80,7 +80,7 @@ if (s.at(0) == '{') { istringstream in(s); in >> std::noskipws; in.get(); // skip '{' - while (!in.eof()) { + while (has_data(in)) { string key = slurp_key(in); if (key.empty()) continue; if (key == "}") continue; diff --git a/055parse_tree.cc b/055parse_tree.cc index 8f93c1c7..ef9cf4e1 100644 --- a/055parse_tree.cc +++ b/055parse_tree.cc @@ -29,7 +29,7 @@ string_tree* parse_string_tree(const string& s) { string_tree* parse_string_tree(istream& in) { skip_whitespace(in); - if (in.eof()) return NULL; + if (!has_data(in)) return NULL; if (in.peek() == ')') { in.get(); return NULL; @@ -42,7 +42,7 @@ string_tree* parse_string_tree(istream& in) { string_tree* result = NULL; string_tree** curr = &result; while (in.peek() != ')') { - assert(!in.eof()); + assert(has_data(in)); *curr = new string_tree(""); skip_whitespace(in); skip_ignored_characters(in); diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc index 02042ac2..c7bc38ac 100644 --- a/058shape_shifting_container.cc +++ b/058shape_shifting_container.cc @@ -49,7 +49,7 @@ void read_type_ingredients(string& name) { put(Type_ordinal, name, Next_type_ordinal++); type_info& info = get_or_insert(Type, get(Type_ordinal, name)); long long int next_type_ordinal = START_TYPE_INGREDIENTS; - while (!in.eof()) { + while (has_data(in)) { string curr = slurp_until(in, ':'); if (info.type_ingredient_names.find(curr) != info.type_ingredient_names.end()) { raise_error << "can't repeat type ingredient names in a single container definition\n" << end(); diff --git a/092persist.cc b/092persist.cc index 774ce08f..e0201cd0 100644 --- a/092persist.cc +++ b/092persist.cc @@ -57,7 +57,7 @@ string slurp(const string& filename) { if (!fin) return result.str(); // don't bother checking errno const int N = 1024; char buf[N]; - while (!fin.eof()) { + while (has_data(fin)) { bzero(buf, N); fin.read(buf, N-1); // leave at least one null result << buf; |