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
This commit is contained in:
Oliver Kahrmann 2021-05-25 20:51:08 +02:00
parent 0c4594f59a
commit 58542d36be
No known key found for this signature in database
GPG Key ID: 55452A28EC97940F
3 changed files with 18 additions and 3 deletions

View File

@ -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

View File

@ -1977,7 +1977,9 @@ result<Value, std::string> 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

View File

@ -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