0030964: Data Exchange - use Standard_ReadLineBuffer within OBJ reader
[occt.git] / src / Standard / Standard_ReadLineBuffer.hxx
index 94ae850..5e320df 100644 (file)
@@ -26,6 +26,7 @@ public:
   //! @param theMaxBufferSizeBytes the length of buffer to read (in bytes)
   Standard_ReadLineBuffer (size_t theMaxBufferSizeBytes)
   : myUseReadBufferLastStr(false),
+    myIsMultilineMode     (false),
     myBufferPos           (0),
     myBytesLastRead       (0)
   {
@@ -41,6 +42,7 @@ public:
   {
     myReadBufferLastStr.clear();
     myUseReadBufferLastStr = false;
+    myIsMultilineMode = false;
     myBufferPos = 0;
     myBytesLastRead = 0;
   }
@@ -71,6 +73,7 @@ public:
                         int64_t& theReadData)
   {
     char* aResultLine = NULL;
+    bool isMultiline = false;
     theLineLength = 0;
     theReadData = 0;
 
@@ -97,7 +100,7 @@ public:
           if (myUseReadBufferLastStr)
           {
             theLineLength = myReadBufferLastStr.size();
-            aResultLine = myReadBufferLastStr.data();
+            aResultLine = &myReadBufferLastStr.front();
             myUseReadBufferLastStr = false;
           }
           break;
@@ -110,9 +113,64 @@ public:
       // read next line from myReadBuffer
       while (myBufferPos < myBytesLastRead)
       {
-        if (myReadBuffer[myBufferPos] == '\n')
+        if (myReadBuffer[myBufferPos] == '\\' && myIsMultilineMode)
         {
-          isEndLineFound = true;
+          // multi-line syntax
+          if (myBufferPos + 1 == myBytesLastRead
+           ||(myBufferPos + 2 == myBytesLastRead && myReadBuffer[myBufferPos + 1] == '\r'))
+          {
+            isMultiline = true;
+          }
+          else if (myReadBuffer[myBufferPos + 1] == '\n'
+                ||(myReadBuffer[myBufferPos + 1] == '\r' && myReadBuffer[myBufferPos + 2] == '\n'))
+          {
+            if (myUseReadBufferLastStr)
+            {
+              myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
+            }
+            else
+            {
+              myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
+              myUseReadBufferLastStr = true;
+            }
+
+            if (myReadBuffer[myBufferPos + 1] == '\r')
+            {
+              myBufferPos += 2;
+            }
+            else
+            {
+              myBufferPos += 1;
+            }
+
+            aStartLinePos = myBufferPos + 1;
+          }
+        }
+        else if (myReadBuffer[myBufferPos] == '\n')
+        {
+          if (!isMultiline)
+          {
+            isEndLineFound = true;
+          }
+          else if (myBufferPos == 1 && myReadBuffer[0] == '\r')
+          {
+            myReadBufferLastStr.erase (myReadBufferLastStr.end() - 1);
+            aStartLinePos += 2;
+            isMultiline = false;
+          }
+          else if (myBufferPos == 0)
+          {
+            aStartLinePos += 1;
+            if (myReadBufferLastStr[myReadBufferLastStr.size() - 1] == '\\')
+            {
+              myReadBufferLastStr.erase (myReadBufferLastStr.end() - 1);
+            }
+            else
+            {
+              myReadBufferLastStr.erase (myReadBufferLastStr.end() - 2, myReadBufferLastStr.end());
+            }
+            isMultiline = false;
+          }
         }
 
         ++myBufferPos;
@@ -128,7 +186,7 @@ public:
           myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
           myUseReadBufferLastStr = false;
           theLineLength = myReadBufferLastStr.size();
-          aResultLine = myReadBufferLastStr.data();
+          aResultLine = &myReadBufferLastStr.front();
         }
         else
         {
@@ -137,7 +195,7 @@ public:
             myReadBufferLastStr.clear();
           }
           theLineLength = myBufferPos - aStartLinePos;
-          aResultLine = myReadBuffer.data() + aStartLinePos;
+          aResultLine = &myReadBuffer.front() + aStartLinePos;
         }
         // make string null terminated by replacing '\n' or '\r' (before '\n') symbol to null character.
         if (theLineLength > 1 && aResultLine[theLineLength - 2] == '\r')
@@ -156,14 +214,27 @@ public:
         // save "unfinished" part of string to additional buffer
         if (aStartLinePos != myBufferPos)
         {
-          myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
-          myUseReadBufferLastStr = true;
+          if (myUseReadBufferLastStr)
+          {
+            myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
+          }
+          else
+          {
+            myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
+            myUseReadBufferLastStr = true;
+          }
         }
       }
     }
     return aResultLine;
   }
 
+  //! Returns TRUE when the Multiline Mode is on.
+  bool IsMultilineMode() const { return myIsMultilineMode; }
+
+  //! Sets or unsets the multi-line mode.
+  void SetMultilineMode (bool theMultilineMode) { myIsMultilineMode = theMultilineMode; }
+
 protected:
 
   //! Read from stl stream.
@@ -172,7 +243,7 @@ protected:
                    size_t theLen,
                    size_t& theReadLen)
   {
-    theReadLen = (size_t )theStream.read (myReadBuffer.data(), theLen).gcount();
+    theReadLen = (size_t )theStream.read (&myReadBuffer.front(), theLen).gcount();
     return !theStream.bad();
   }
 
@@ -182,7 +253,7 @@ protected:
                    size_t theLen,
                    size_t& theReadLen)
   {
-    theReadLen = ::fread (myReadBuffer.data(), 1, theLen, theStream);
+    theReadLen = ::fread (&myReadBuffer.front(), 1, theLen, theStream);
     return ::ferror (theStream) == 0;
   }
 
@@ -191,6 +262,7 @@ protected:
   std::vector<char> myReadBuffer;           //!< Temp read buffer
   std::vector<char> myReadBufferLastStr;    //!< Part of last string of myReadBuffer
   bool              myUseReadBufferLastStr; //!< Flag to use myReadBufferLastStr during next line reading
+  bool              myIsMultilineMode;      //!< Flag to process of the special multi-line case at the end of the line
   size_t            myBufferPos;            //!< Current position in myReadBuffer
   size_t            myBytesLastRead;        //!< The number of characters that were read last time from myReadBuffer.
 };