[Bf-blender-cvs] [aacb1f4756a] soc-2020-io-performance: Use stoi and stof instead of >> for faster parsing.

Ankit Meel noreply at git.blender.org
Wed Jul 15 00:33:02 CEST 2020


Commit: aacb1f4756abcb725fa3b9729a4e669b4e52c410
Author: Ankit Meel
Date:   Wed Jul 15 04:02:51 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rBaacb1f4756abcb725fa3b9729a4e669b4e52c410

Use stoi and stof instead of >>  for faster parsing.

===================================================================

M	source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc

===================================================================

diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
index 82a3831844d..bc708678559 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_im_file_reader.cc
@@ -34,32 +34,51 @@
 
 namespace blender::io::obj {
 
+using std::string;
+
 OBJImporter::OBJImporter(const OBJImportParams &import_params) : import_params_(import_params)
 {
   infile_.open(import_params_.filepath);
 }
 
-static void split_by_char(std::string in_string, char delimiter, Vector<std::string> &r_out_list)
+static void split_by_char(string in_string, char delimiter, Vector<string> &r_out_list)
 {
   std::stringstream stream(in_string);
-  std::string word{};
+  string word{};
   while (std::getline(stream, word, delimiter)) {
+    if (word == "" || word[0] == ' ' || word[0] == '\0') {
+      continue;
+    }
     r_out_list.append(word);
   }
 }
 
+static string first_word_of_string(string in_string)
+{
+  size_t pos = in_string.find_first_of(' ');
+  return pos == string::npos ? in_string.substr(0, 1) : in_string.substr(0, pos);
+}
+
+MALWAYS_INLINE void copy_string_to_float(float *dst, Span<string> src)
+{
+  dst[0] = std::stof(src[0]);
+  dst[1] = std::stof(src[1]);
+  if (src.size() == 3) {
+    dst[2] = std::stof(src[2]);
+  }
+}
+
 void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of_objects)
 {
-  std::string line;
+  string line;
   /* Non owning raw pointer to the unique_ptr to a raw object.
    * Needed to update object data in the same while loop.
    * TODO ankitm Try to move the rest of the data parsing code in a conditional depending on a
    * valid "o" object. */
   std::unique_ptr<OBJRawObject> *curr_ob;
   while (std::getline(infile_, line)) {
-    std::stringstream s_line(line);
-    std::string line_key;
-    s_line >> line_key;
+    string line_key = first_word_of_string(line);
+    std::stringstream s_line(line.substr(line_key.size()));
 
     if (line_key == "o") {
       /* Update index offsets if an object has been processed already. */
@@ -73,7 +92,9 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
     /* TODO ankitm Check that an object exists. */
     else if (line_key == "v") {
       MVert curr_vert;
-      s_line >> curr_vert.co[0] >> curr_vert.co[1] >> curr_vert.co[2];
+      Vector<string> str_vert;
+      split_by_char(s_line.str(), ' ', str_vert);
+      copy_string_to_float(curr_vert.co, str_vert);
       (*curr_ob)->vertices.append(curr_vert);
     }
     else if (line_key == "vn") {
@@ -81,20 +102,17 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
     }
     else if (line_key == "vt") {
       MLoopUV curr_tex_vert;
-      s_line >> curr_tex_vert.uv[0] >> curr_tex_vert.uv[1];
+      Vector<string> str_vert;
+      split_by_char(s_line.str(), ' ', str_vert);
+      copy_string_to_float(curr_tex_vert.uv, str_vert);
       (*curr_ob)->texture_vertices.append(curr_tex_vert);
     }
     else if (line_key == "f") {
       OBJFaceElem curr_face;
-      std::string str_corners_line = s_line.str();
-      Vector<std::string> str_corners_split;
+      string str_corners_line = s_line.str();
+      Vector<string> str_corners_split;
       split_by_char(str_corners_line, ' ', str_corners_split);
       for (auto str_corner : str_corners_split) {
-        if (str_corner == "f") {
-          /* Hack, since that's how streams change to strings. Ideally the line_key should be a
-           * string and then a stream is made from the rest of the line. */
-          continue;
-        }
         OBJFaceCorner corner;
         size_t n_slash = std::count(str_corner.begin(), str_corner.end(), '/');
         if (n_slash == 0) {
@@ -104,7 +122,7 @@ void OBJImporter::parse_and_store(Vector<std::unique_ptr<OBJRawObject>> &list_of
           Vector<std::string> vert_texture;
           split_by_char(str_corner, '/', vert_texture);
           corner.vert_index = std::stoi(vert_texture[0]);
-          corner.tex_vert_index = vert_texture[1].empty() ? -1 : std::stoi(vert_texture[1]);
+          corner.tex_vert_index = vert_texture.size() >= 1 ? -1 : std::stoi(vert_texture[1]);
         }
         else if (n_slash == 2) {
           Vector<std::string> vert_normal;



More information about the Bf-blender-cvs mailing list