diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2021-01-19 20:28:40 +0100 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2021-01-19 21:44:22 +0100 | 
| commit | b60e7b5e07033b926c29042ba6b267d5af32f7e3 (patch) | |
| tree | 864ea0623e5111058ddfe586e280469009909065 /src | |
| parent | ec8ec7eb2a0b677f80f89834d955d1f0aa614538 (diff) | |
Storage: handle parsing errors without throwing exceptions
Diffstat (limited to 'src')
| -rw-r--r-- | src/storage.cpp | 26 | 
1 files changed, 21 insertions, 5 deletions
| diff --git a/src/storage.cpp b/src/storage.cpp index 4f48c67..51ce9bc 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -24,12 +24,14 @@ using std::copy;  using std::get;  using std::holds_alternative;  using std::ifstream; +using std::invalid_argument;  using std::is_same_v;  using std::make_shared;  using std::make_unique;  using std::monostate;  using std::nullopt;  using std::ofstream; +using std::out_of_range;  using std::runtime_error;  using std::scoped_lock;  using std::shared_ptr; @@ -980,12 +982,12 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,  	while (begin != end) {  		const auto colon = std::find(begin, end, ':');  		if (colon == end) -			throw runtime_error("invalid record"); +			return nullopt;  		const string name(begin, colon);  		const auto space = std::find(colon + 1, end, ' ');  		if (space == end) -			throw runtime_error("invalid record"); +			return nullopt;  		const string type(colon + 1, space);  		begin = space + 1; @@ -993,7 +995,7 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,  		for (bool cont = true; cont; ) {  			auto newline = std::find(begin, end, '\n');  			if (newline == end) -				throw runtime_error("invalid record"); +				return nullopt;  			if (newline + 1 != end && *(newline + 1) == '\t')  				newline++; @@ -1005,7 +1007,13 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,  		}  		if (type == "i") -			items->emplace_back(name, std::stoi(value)); +			try { +				items->emplace_back(name, std::stoi(value)); +			} catch (invalid_argument &) { +				return nullopt; +			} catch (out_of_range &) { +				return nullopt; // TODO +			}  		else if (type == "t")  			items->emplace_back(name, value);  		else if (type == "b") @@ -1163,7 +1171,15 @@ ObjectT<S>::decodePrefix(const S & st,  	if (space == newline)  		return nullopt; -	ssize_t size = std::stoi(string(space + 1, newline)); +	ssize_t size; +	try { +		size = std::stol(string(space + 1, newline)); +	} catch (invalid_argument &) { +		return nullopt; +	} catch (out_of_range &) { +		// Way too big to handle anyway +		return nullopt; +	}  	if (end - newline - 1 < size)  		return nullopt;  	auto cend = newline + 1 + size; |