Attempt to catch out-of-range error
This commit is contained in:
parent
2e67c5925b
commit
587db88565
|
|
@ -11,6 +11,7 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
|
||||
namespace CesiumGltf {
|
||||
/**
|
||||
|
|
@ -196,17 +197,19 @@ struct MetadataConversions<
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char* pLastUsed;
|
||||
int64_t parsedValue = std::strtoll(from.c_str(), &pLastUsed, 10);
|
||||
if (pLastUsed == from.c_str() + from.size()) {
|
||||
if (errno != ERANGE && pLastUsed == from.c_str() + from.size()) {
|
||||
// Successfully parsed the entire string as an integer of this type.
|
||||
return CesiumUtility::losslessNarrow<TTo, int64_t>(parsedValue);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
// Failed to parse as an integer. Maybe we can parse as a double and
|
||||
// truncate it?
|
||||
double parsedDouble = std::strtod(from.c_str(), &pLastUsed);
|
||||
if (pLastUsed == from.c_str() + from.size()) {
|
||||
if (errno != ERANGE && pLastUsed == from.c_str() + from.size()) {
|
||||
// Successfully parsed the entire string as a double.
|
||||
// Convert it to an integer if we can.
|
||||
double truncated = glm::trunc(parsedDouble);
|
||||
|
|
@ -218,6 +221,7 @@ struct MetadataConversions<
|
|||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
|
@ -248,17 +252,22 @@ struct MetadataConversions<
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char* pLastUsed;
|
||||
uint64_t parsedValue = std::strtoull(from.c_str(), &pLastUsed, 10);
|
||||
if (pLastUsed == from.c_str() + from.size()) {
|
||||
if (errno == ERANGE) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (errno != ERANGE && pLastUsed == from.c_str() + from.size()) {
|
||||
// Successfully parsed the entire string as an integer of this type.
|
||||
return CesiumUtility::losslessNarrow<TTo, uint64_t>(parsedValue);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
// Failed to parse as an integer. Maybe we can parse as a double and
|
||||
// truncate it?
|
||||
double parsedDouble = std::strtod(from.c_str(), &pLastUsed);
|
||||
if (pLastUsed == from.c_str() + from.size()) {
|
||||
if (errno != ERANGE && pLastUsed == from.c_str() + from.size()) {
|
||||
// Successfully parsed the entire string as a double.
|
||||
// Convert it to an integer if we can.
|
||||
double truncated = glm::trunc(parsedDouble);
|
||||
|
|
@ -270,6 +279,7 @@ struct MetadataConversions<
|
|||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ TEST_CASE("Test MetadataConversions for boolean") {
|
|||
REQUIRE(MetadataConversions<bool, int8_t>::convert(0) == false);
|
||||
}
|
||||
|
||||
SECTION("converts from string") {
|
||||
SECTION("converts from string view") {
|
||||
std::string_view stringView("true");
|
||||
REQUIRE(
|
||||
MetadataConversions<bool, std::string_view>::convert(stringView) ==
|
||||
|
|
@ -49,7 +49,16 @@ TEST_CASE("Test MetadataConversions for boolean") {
|
|||
false);
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible strings") {
|
||||
SECTION("converts from string") {
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("true") == true);
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("yes") == true);
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("1") == true);
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("false") == false);
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("no") == false);
|
||||
REQUIRE(MetadataConversions<bool, std::string>::convert("0") == false);
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible string views") {
|
||||
std::string_view stringView("11");
|
||||
// invalid number
|
||||
REQUIRE(!MetadataConversions<bool, std::string_view>::convert(stringView));
|
||||
|
|
@ -59,6 +68,15 @@ TEST_CASE("Test MetadataConversions for boolean") {
|
|||
REQUIRE(!MetadataConversions<bool, std::string_view>::convert(stringView));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible strings") {
|
||||
// invalid number
|
||||
REQUIRE(!MetadataConversions<bool, std::string_view>::convert("11"));
|
||||
|
||||
// invalid word
|
||||
REQUIRE(
|
||||
!MetadataConversions<bool, std::string_view>::convert("this is true"));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible types") {
|
||||
// vecN
|
||||
REQUIRE(!MetadataConversions<bool, glm::vec3>::convert(glm::vec3(1, 2, 3)));
|
||||
|
|
@ -90,7 +108,7 @@ TEST_CASE("Test MetadataConversions for integer") {
|
|||
REQUIRE(MetadataConversions<int32_t, bool>::convert(false) == 0);
|
||||
}
|
||||
|
||||
SECTION("converts from string") {
|
||||
SECTION("converts from string view") {
|
||||
// integer string
|
||||
std::string_view value("-123");
|
||||
REQUIRE(
|
||||
|
|
@ -101,6 +119,17 @@ TEST_CASE("Test MetadataConversions for integer") {
|
|||
MetadataConversions<int32_t, std::string_view>::convert(value) == 123);
|
||||
}
|
||||
|
||||
SECTION("converts from string") {
|
||||
// integer string
|
||||
REQUIRE(
|
||||
MetadataConversions<int32_t, std::string_view>::convert("-123") ==
|
||||
-123);
|
||||
// double string
|
||||
REQUIRE(
|
||||
MetadataConversions<int32_t, std::string_view>::convert("123.456") ==
|
||||
123);
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for out-of-range numbers") {
|
||||
// out-of-range unsigned int
|
||||
REQUIRE(!MetadataConversions<int32_t, uint32_t>::convert(
|
||||
|
|
@ -115,21 +144,33 @@ TEST_CASE("Test MetadataConversions for integer") {
|
|||
std::numeric_limits<double>::max()));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for invalid strings") {
|
||||
SECTION("returns std::nullopt for invalid string views") {
|
||||
// out-of-range number
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string_view>::convert(
|
||||
std::string_view("-255")));
|
||||
REQUIRE(!MetadataConversions<uint64_t, std::string_view>::convert(
|
||||
std::string_view("-1")));
|
||||
// mixed number and non-number input
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string_view>::convert(
|
||||
std::string_view("10 hello")));
|
||||
// non-number input
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string_view>::convert(
|
||||
REQUIRE(!MetadataConversions<uint8_t, std::string_view>::convert(
|
||||
std::string_view("not a number")));
|
||||
// empty input
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string_view>::convert(
|
||||
std::string_view()));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for invalid strings") {
|
||||
// out-of-range number
|
||||
REQUIRE(!MetadataConversions<uint64_t, std::string>::convert("-1"));
|
||||
// mixed number and non-number input
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string>::convert("10 hello"));
|
||||
// non-number input
|
||||
REQUIRE(
|
||||
!MetadataConversions<uint8_t, std::string>::convert("not a number"));
|
||||
// empty input
|
||||
REQUIRE(!MetadataConversions<int8_t, std::string>::convert(""));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible types") {
|
||||
// vecN
|
||||
REQUIRE(!MetadataConversions<int32_t, glm::ivec3>::convert(
|
||||
|
|
@ -168,7 +209,7 @@ TEST_CASE("Test MetadataConversions for float") {
|
|||
REQUIRE(MetadataConversions<float, bool>::convert(false) == 0.0f);
|
||||
}
|
||||
|
||||
SECTION("converts from string") {
|
||||
SECTION("converts from string view") {
|
||||
REQUIRE(
|
||||
MetadataConversions<float, std::string_view>::convert(
|
||||
std::string_view("123")) == static_cast<float>(123));
|
||||
|
|
@ -177,7 +218,16 @@ TEST_CASE("Test MetadataConversions for float") {
|
|||
std::string_view("123.456")) == static_cast<float>(123.456));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for invalid strings") {
|
||||
SECTION("converts from string") {
|
||||
REQUIRE(
|
||||
MetadataConversions<float, std::string>::convert("123") ==
|
||||
static_cast<float>(123));
|
||||
REQUIRE(
|
||||
MetadataConversions<float, std::string>::convert("123.456") ==
|
||||
static_cast<float>(123.456));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for invalid string views") {
|
||||
// out-of-range number
|
||||
REQUIRE(!MetadataConversions<float, std::string_view>::convert(
|
||||
std::string_view(std::to_string(std::numeric_limits<double>::max()))));
|
||||
|
|
@ -192,6 +242,18 @@ TEST_CASE("Test MetadataConversions for float") {
|
|||
std::string_view()));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for invalid strings") {
|
||||
// out-of-range number
|
||||
REQUIRE(!MetadataConversions<float, std::string>::convert(
|
||||
std::to_string(std::numeric_limits<double>::max())));
|
||||
// mixed number and non-number input
|
||||
REQUIRE(!MetadataConversions<float, std::string>::convert("10.00f hello"));
|
||||
// non-number input
|
||||
REQUIRE(!MetadataConversions<float, std::string>::convert("not a number"));
|
||||
// empty input
|
||||
REQUIRE(!MetadataConversions<float, std::string>::convert(""));
|
||||
}
|
||||
|
||||
SECTION("returns std::nullopt for incompatible types") {
|
||||
// vecN
|
||||
REQUIRE(
|
||||
|
|
|
|||
Loading…
Reference in New Issue