From 58542d36be5372f3efa35c30d7bb4e58863fad80 Mon Sep 17 00:00:00 2001 From: Oliver Kahrmann Date: Tue, 25 May 2021 20:51:08 +0200 Subject: [PATCH] Preserve empty location for empty files Without a region, error messages in exceptions are unable to print a filename. By retaining the location in a zero-length region and detecting this when formatting the exception text it is possible to print the filename and explicitly state that the file is completely empty. Fixes #160 --- README.md | 2 ++ toml/parser.hpp | 4 +++- toml/value.hpp | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 23d759e..8905209 100644 --- a/README.md +++ b/README.md @@ -1943,6 +1943,8 @@ I appreciate the help of the contributors who introduced the great feature to th - Add missing include files - sneakypete81 (@sneakypete81) - Fix typo in error message +- Oliver Kahrmann (@founderio) + - Fix missing filename in error message if parsed file is empty ## Licensing terms diff --git a/toml/parser.hpp b/toml/parser.hpp index 231df80..f6d6d83 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -1977,7 +1977,9 @@ result parse_toml_file(location& loc) const auto first = loc.iter(); if(first == loc.end()) { - return ok(value_type(table_type{} /*, empty file has no region ...*/)); + // For empty files, return an empty table with an empty region (zero-length). + // Without the region, error messages would miss the filename. + return ok(value_type(table_type{}, region(loc, first, first), {})); } // put the first line as a region of a file diff --git a/toml/value.hpp b/toml/value.hpp index ed8c76e..7c68514 100644 --- a/toml/value.hpp +++ b/toml/value.hpp @@ -66,9 +66,20 @@ throw_key_not_found_error(const Value& v, const key& ky) // ``` // It actually points to the top-level table at the first character, // not `[table]`. But it is too confusing. To avoid the confusion, the error - // message should explicitly say "key not found in the top-level table". + // message should explicitly say "key not found in the top-level table", + // or "the parsed file is empty" if there is no content at all (0 bytes in file). const auto loc = v.location(); - if(loc.line() == 1 && loc.region() == 1) + if(loc.line() == 1 && loc.region() == 0) + { + // First line with a zero-length region means "empty file". + // The region will be generated at `parse_toml_file` function + // if the file contains no bytes. + throw std::out_of_range(format_underline(concat_to_string( + "key \"", ky, "\" not found in the top-level table"), { + {loc, "the parsed file is empty"} + })); + } + else if(loc.line() == 1 && loc.region() == 1) { // Here it assumes that top-level table starts at the first character. // The region corresponds to the top-level table will be generated at