From e4c4a3db73ff68ed55d9bd4d086d14d574cdafc8 Mon Sep 17 00:00:00 2001
From: Martin Schultz <Martin.Schultz@RWTH-Aachen.de>
Date: Wed, 14 May 2014 20:06:42 +0200
Subject: [PATCH] * changed stream operations in objloader to be pointer
 operations

---
 .../OpenGL/Data/GeometryDataLoadStoreOBJ.cc   | 102 ++++++++++--------
 1 file changed, 60 insertions(+), 42 deletions(-)

diff --git a/src/ACGL/OpenGL/Data/GeometryDataLoadStoreOBJ.cc b/src/ACGL/OpenGL/Data/GeometryDataLoadStoreOBJ.cc
index a6245400..889cc4ab 100644
--- a/src/ACGL/OpenGL/Data/GeometryDataLoadStoreOBJ.cc
+++ b/src/ACGL/OpenGL/Data/GeometryDataLoadStoreOBJ.cc
@@ -7,6 +7,7 @@
 #include <ACGL/OpenGL/Data/GeometryDataLoadStore.hh>
 #include <ACGL/Math/Math.hh>
 #include <ACGL/Utils/StringHelpers.hh>
+#include <ACGL/Utils/MemoryMappedFile.hh>
 
 #include <fstream>
 #include <string>
@@ -31,50 +32,62 @@ namespace
         int normal;
     };
 
-    void skipLine(std::fstream& _stream)
-    {
-        _stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
-    }
-
     // Parses a string of space-separated numbers into a packed floating-point vector (_data) with a maximum number of _maxDimension elements
-    void parseVector(const std::string& _string, int _maxDimension, int& _dimension, float* _data)
+    void parseVector(const char* _start , const char* _end, int _maxDimension, int& _dimension, float* _data)
     {
-        std::stringstream stream(_string);
-        float temp;
+        const char* it = _start;
+        if (*it == ' ')
+        {
+            it++;
+        }
+        const char* end = _end;
+        const char* found;
         _dimension = 0;
-        while(stream >> temp && _dimension < _maxDimension)
+        while (_dimension < _maxDimension && it < end)
         {
-            _data[_dimension] = temp;
-            _dimension++;
+            found = std::find(it, end, ' ');
+            _data[_dimension++] = std::atof(it);
+            it = found == end ? end : found + 1;
         }
     }
 
     // Turns an index parameter string into a std::vector of IndexTuples, e.g.
     // "1//2 3//4 5//6" --> { IndexTuple(1, -1, 2), IndexTuple(3, -1, 4), IndexTuple(5, -1, 6) }
-    std::vector<IndexTuple> parseIndices(const std::string& _string)
+    std::vector<IndexTuple> parseIndices(const char* _start, const char* _end)
     {
         std::vector<IndexTuple> indices;
 
-        std::stringstream stream(_string);
+        const char* it = _start;
+        if (*it == ' ') //skip starting whitespace
+            it++;
+        const char* vsit;
+        const char* vsend;
+        const char* foundSlash;
         std::string vertexString;
-        while(stream >> vertexString)
+        std::string component;
+        int componentIndex;
+        int index;
+        while (it < _end)
         {
-            std::vector<std::string> componentsString = ACGL::Utils::StringHelpers::split(vertexString, '/', false);
+            vsit = it;
+            vsend = std::find(it, _end, ' ');
+            componentIndex = 0;
             IndexTuple indexTuple;
-
-            for(int i = 0; i < std::min<int>(componentsString.size(), 3); ++i)
+            indices.push_back(indexTuple);
+            //process the string now meaning we split by /
+            while (vsit < vsend)
             {
-                std::string& componentString = componentsString[i];
-                int index = atoi(componentString.c_str());
-
-                if(i == 0) indexTuple.position = index-1;
-                if(i == 1) indexTuple.texCoord = index-1;
-                if(i == 2) indexTuple.normal   = index-1;
+                foundSlash = std::find(vsit, vsend, '/');
+                index = std::atoi(vsit);
+                if (componentIndex == 0) indices.back().position = index - 1;
+                if (componentIndex == 1) indices.back().texCoord = index - 1;
+                if (componentIndex == 2) indices.back().normal = index - 1;
+                componentIndex++;
+                vsit = foundSlash == vsend ? vsend : foundSlash + 1;
             }
-
-            indices.push_back(indexTuple);
+            //indices.push_back(indexTuple);
+            it = vsend == _end ? _end : vsend + 1;
         }
-
         return indices;
     }
 }
@@ -89,13 +102,14 @@ namespace OpenGL{
 SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _computeNormals)
 {
     SharedGeometryData data;
-
-    std::fstream file(_filename.c_str(), std::ios_base::in);
-    if(!file.good())
+    MemoryMappedFile mmf(_filename.c_str());
+    if(mmf.errorCode())
     {
         error() << "could not open file " << _filename << std::endl;
         return data;
     }
+    const char* pchBuf = mmf.data();
+    const char* pchEnd = pchBuf + mmf.length();
 
     GLenum primitiveType = GL_INVALID_ENUM;
     bool hasTexCoords = false;
@@ -111,27 +125,30 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
     std::vector<IndexTuple> indices;
 
     std::string keyword;
-    std::string parameters;
-    while(file.good())
+    const char* parameters[2];
+    while (pchBuf < pchEnd)
     {
         // Parse the current line
+        const char* pchEOL = std::find(pchBuf, pchEnd, '\n');
 
         // If the line starts with a #, it is a comment
-        if(file.peek() == '#')
+        if (*pchBuf == '#')
         {
-            skipLine(file);
+            pchBuf = pchEOL + 1;
             continue;
         }
 
         // Otherwise, extract the first word and the remainder
-        file >> keyword;
-        std::getline(file, parameters);
+        const char* pchKey = std::find(pchBuf, pchEnd, ' ');
+        keyword = std::string(pchBuf, pchKey);
+        parameters[0] = pchKey + 1;
+        parameters[1] = pchEOL;
 
         if(keyword == "v") // vertex position
         {
             glm::vec4 position;
             int dimension;
-            parseVector(parameters, 4, dimension, (float*)&position);
+            parseVector(parameters[0], parameters[1], 4, dimension, (float*)&position);
             if(dimension < 4) position.w = 1.0;
 
             if(dimension < 3)
@@ -146,7 +163,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
         {
             glm::vec3 texCoord;
             int dimension;
-            parseVector(parameters, 3, dimension, (float*)&texCoord);
+            parseVector(parameters[0], parameters[1], 3, dimension, (float*)&texCoord);
 
             if(texCoordDimension < 0)
                 texCoordDimension = dimension;
@@ -164,7 +181,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
         {
             glm::vec3 normal;
             int dimension;
-            parseVector(parameters, 3, dimension, (float*)&normal);
+            parseVector(parameters[0], parameters[1], 3, dimension, (float*)&normal);
 
             if(dimension < 3)
             {
@@ -186,7 +203,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
                 return data;
             }
 
-            std::vector<IndexTuple> pointIndices = parseIndices(parameters);
+            std::vector<IndexTuple> pointIndices = parseIndices(parameters[0], parameters[1]);
             // points are just added in order
             for(size_t i = 0; i < pointIndices.size(); ++i)
             {
@@ -203,7 +220,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
                 return data;
             }
 
-            std::vector<IndexTuple> lineIndices = parseIndices(parameters);
+            std::vector<IndexTuple> lineIndices = parseIndices(parameters[0], parameters[1]);
             // add line segments for the line strip defined by the vertices
             for(size_t i = 0; i < lineIndices.size() - 1; ++i)
             {
@@ -221,7 +238,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
                 return data;
             }
 
-            std::vector<IndexTuple> faceIndices = parseIndices(parameters);
+            std::vector<IndexTuple> faceIndices = parseIndices(parameters[0], parameters[1]);
             // triangulate the polygon defined by the indices
             for(size_t i = 1; i < faceIndices.size() - 1; ++i)
             {
@@ -256,6 +273,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
         {
             warning() << "unknown OBJ keyword ignored: " << keyword << std::endl;
         }
+        pchBuf = pchEOL + 1;
     }
 
     if (!hasNormals && _computeNormals) {
@@ -349,7 +367,7 @@ SharedGeometryData loadGeometryDataFromOBJ(const std::string& _filename, bool _c
     data->setStrideSize(strideSize);
     data->setSize(abDataElements * sizeof(GLfloat));
     data->setData((GLubyte*)abData);
-
+    std::exit(0);
     return data;
 }
 
-- 
GitLab