Skip to content

Commit 7b410a0

Browse files
committed
Support paring leadingdecimal dot of floating point value. Fixes #201
1 parent 17a6941 commit 7b410a0

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
newmtl default
2+
Ka 0 0 0
3+
Kd 0 0 0
4+
Ks 0 0 0
5+
Kt 0.1 0.2 0.3
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mtllib leading-decimal-dot-issue-201.mtl
2+
o Test
3+
v .8e-1 -.7e+2 -5.532511
4+
v .575869 -.666304 5.896140
5+
v .940448 1.000000 -1.971128
6+
usemtl default
7+
f 1 2 3

tests/tester.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,35 @@ TEST_CASE("colorspace", "[Issue184]") {
10801080
REQUIRE(0 == materials[0].bump_texopt.colorspace.compare("linear"));
10811081
}
10821082

1083+
TEST_CASE("leading-decimal-dots", "[Issue201]") {
1084+
tinyobj::attrib_t attrib;
1085+
std::vector<tinyobj::shape_t> shapes;
1086+
std::vector<tinyobj::material_t> materials;
1087+
1088+
std::string warn;
1089+
std::string err;
1090+
bool ret =
1091+
tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err,
1092+
"../models/leading-decimal-dot-issue-201.obj", gMtlBasePath);
1093+
1094+
if (!warn.empty()) {
1095+
std::cout << "WARN: " << warn << std::endl;
1096+
}
1097+
1098+
if (!err.empty()) {
1099+
std::cerr << "ERR: " << err << std::endl;
1100+
}
1101+
1102+
REQUIRE(true == ret);
1103+
REQUIRE(1 == shapes.size());
1104+
REQUIRE(1 == materials.size());
1105+
REQUIRE(0.8e-1 == Approx(attrib.vertices[0]));
1106+
REQUIRE(-.7e+2 == Approx(attrib.vertices[1]));
1107+
REQUIRE(.575869 == Approx(attrib.vertices[3]));
1108+
REQUIRE(-.666304 == Approx(attrib.vertices[4]));
1109+
REQUIRE(.940448 == Approx(attrib.vertices[6]));
1110+
}
1111+
10831112
// Fuzzer test.
10841113
// Just check if it does not crash.
10851114
// Disable by default since Windows filesystem can't create filename of afl

tiny_obj_loader.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
741741
int read = 0;
742742
// Tells whether a loop terminated due to reaching s_end.
743743
bool end_not_reached = false;
744+
bool leading_decimal_dots = false;
744745

745746
/*
746747
BEGIN PARSING.
@@ -750,23 +751,35 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
750751
if (*curr == '+' || *curr == '-') {
751752
sign = *curr;
752753
curr++;
754+
if ((curr != s_end) && (*curr == '.')) {
755+
// accept. Somethig like `.7e+2`, `-.5234`
756+
leading_decimal_dots = true;
757+
}
753758
} else if (IS_DIGIT(*curr)) { /* Pass through. */
759+
} else if (*curr == '.') {
760+
// accept. Somethig like `.7e+2`, `-.5234`
761+
leading_decimal_dots = true;
754762
} else {
755763
goto fail;
756764
}
757765

758766
// Read the integer part.
759767
end_not_reached = (curr != s_end);
760-
while (end_not_reached && IS_DIGIT(*curr)) {
761-
mantissa *= 10;
762-
mantissa += static_cast<int>(*curr - 0x30);
763-
curr++;
764-
read++;
765-
end_not_reached = (curr != s_end);
768+
if (!leading_decimal_dots) {
769+
while (end_not_reached && IS_DIGIT(*curr)) {
770+
mantissa *= 10;
771+
mantissa += static_cast<int>(*curr - 0x30);
772+
curr++;
773+
read++;
774+
end_not_reached = (curr != s_end);
775+
}
766776
}
767777

768778
// We must make sure we actually got something.
769-
if (read == 0) goto fail;
779+
if (!leading_decimal_dots) {
780+
if (read == 0) goto fail;
781+
}
782+
770783
// We allow numbers of form "#", "###" etc.
771784
if (!end_not_reached) goto assemble;
772785

0 commit comments

Comments
 (0)