Fix parsing of crease tags(`t`)
Support parsing texture filename containing whitespace.
diff --git a/models/texture-filename-with-whitespace.mtl b/models/texture-filename-with-whitespace.mtl
new file mode 100644
index 0000000..70b1a4e
--- /dev/null
+++ b/models/texture-filename-with-whitespace.mtl
@@ -0,0 +1,28 @@
+newmtl white
+Ka 0 0 0
+Kd 1 1 1
+Ks 0 0 0
+# filename with white space.
+map_Kd texture 01.png
+
+newmtl red
+Ka 0 0 0
+Kd 1 0 0
+Ks 0 0 0
+# texture option + filename with white space.
+bump -bm 2 bump 01.png
+
+newmtl green
+Ka 0 0 0
+Kd 0 1 0
+Ks 0 0 0
+
+newmtl blue
+Ka 0 0 0
+Kd 0 0 1
+Ks 0 0 0
+
+newmtl light
+Ka 20 20 20
+Kd 1 1 1
+Ks 0 0 0
diff --git a/models/texture-filename-with-whitespace.obj b/models/texture-filename-with-whitespace.obj
new file mode 100644
index 0000000..46e61e7
--- /dev/null
+++ b/models/texture-filename-with-whitespace.obj
@@ -0,0 +1,31 @@
+mtllib texture-filename-with-whitespace.mtl
+
+v 0.000000 2.000000 2.000000
+v 0.000000 0.000000 2.000000
+v 2.000000 0.000000 2.000000
+v 2.000000 2.000000 2.000000
+v 0.000000 2.000000 0.000000
+v 0.000000 0.000000 0.000000
+v 2.000000 0.000000 0.000000
+v 2.000000 2.000000 0.000000
+# 8 vertices
+
+g front cube
+usemtl white
+f 1 2 3 4
+g back cube
+# expects white material
+f 8 7 6 5
+g right cube
+usemtl red
+f 4 3 7 8
+g top cube
+usemtl white
+f 5 1 4 8
+g left cube
+usemtl green
+f 5 6 2 1
+g bottom cube
+usemtl white
+f 2 6 7 3
+# 6 elements
diff --git a/tests/tester.cc b/tests/tester.cc
index 811dfbf..cd972f8 100644
--- a/tests/tester.cc
+++ b/tests/tester.cc
@@ -694,6 +694,29 @@
 
 }
 
+TEST_CASE("texture-name-whitespace", "[Issue145]") {
+  tinyobj::attrib_t attrib;
+  std::vector<tinyobj::shape_t> shapes;
+  std::vector<tinyobj::material_t> materials;
+
+  std::string err;
+  bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/texture-filename-with-whitespace.obj", gMtlBasePath);
+
+  
+  if (!err.empty()) {
+    std::cerr << "[Issue145] " << err << std::endl;
+  }
+
+  REQUIRE(true == ret);
+  REQUIRE(err.empty());
+  REQUIRE(2 < materials.size());
+
+  REQUIRE(0 == materials[0].diffuse_texname.compare("texture 01.png"));
+  REQUIRE(0 == materials[1].bump_texname.compare("bump 01.png"));
+  REQUIRE(2 == Approx(materials[1].bump_texopt.bump_multiplier));
+
+}
+
 #if 0
 int
 main(
diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h
index 591d236..65a9d62 100644
--- a/tiny_obj_loader.h
+++ b/tiny_obj_loader.h
@@ -721,22 +721,24 @@
 static tag_sizes parseTagTriple(const char **token) {
   tag_sizes ts;
 
+  (*token) += strspn((*token), " \t");
   ts.num_ints = atoi((*token));
   (*token) += strcspn((*token), "/ \t\r");
   if ((*token)[0] != '/') {
     return ts;
   }
-  (*token)++;
 
+  (*token)++; // Skip '/'
+
+  (*token) += strspn((*token), " \t");
   ts.num_reals = atoi((*token));
   (*token) += strcspn((*token), "/ \t\r");
   if ((*token)[0] != '/') {
     return ts;
   }
-  (*token)++;
+  (*token)++; // Skip '/'
 
-  ts.num_strings = atoi((*token));
-  (*token) += strcspn((*token), "/ \t\r") + 1;
+  ts.num_strings = parseInt(token);
 
   return ts;
 }
@@ -906,11 +908,18 @@
       parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
     } else {
       // Assume texture filename
+#if 0
       size_t len = strcspn(token, " \t\r");  // untile next space
       texture_name = std::string(token, token + len);
       token += len;
 
       token += strspn(token, " \t");  // skip space
+#else
+      // Read filename until line end to parse filename containing whitespace
+      // TODO(syoyo): Support parsing texture option flag after the filename.
+      texture_name = std::string(token);
+      token += texture_name.length();
+#endif
 
       found_texname = true;
     }
@@ -1762,33 +1771,25 @@
       tag_t tag;
 
       token += 2;
-      std::stringstream ss;
-      ss << token;
-      tag.name = ss.str();
 
-      token += tag.name.size() + 1;
+      tag.name = parseString(&token);
 
       tag_sizes ts = parseTagTriple(&token);
 
       tag.intValues.resize(static_cast<size_t>(ts.num_ints));
 
       for (size_t i = 0; i < static_cast<size_t>(ts.num_ints); ++i) {
-        tag.intValues[i] = atoi(token);
-        token += strcspn(token, "/ \t\r") + 1;
+        tag.intValues[i] = parseInt(&token);
       }
 
       tag.floatValues.resize(static_cast<size_t>(ts.num_reals));
       for (size_t i = 0; i < static_cast<size_t>(ts.num_reals); ++i) {
         tag.floatValues[i] = parseReal(&token);
-        token += strcspn(token, "/ \t\r") + 1;
       }
 
       tag.stringValues.resize(static_cast<size_t>(ts.num_strings));
       for (size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i) {
-        std::stringstream sstr;
-        sstr << token;
-        tag.stringValues[i] = sstr.str();
-        token += tag.stringValues[i].size() + 1;
+        tag.stringValues[i] = parseString(&token);
       }
 
       tags.push_back(tag);