+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools_IStream.hxx>
+#include <Storage_StreamTypeMismatchError.hxx>
+
+//=======================================================================
+//function : BinTools_IStream
+//purpose :
+//=======================================================================
+BinTools_IStream::BinTools_IStream (Standard_IStream& theStream)
+ : myStream (&theStream), myPosition (theStream.tellg()), myLastType (BinTools_ObjectType_Unknown)
+{}
+
+//=======================================================================
+//function : ReadType
+//purpose :
+//=======================================================================
+BinTools_ObjectType BinTools_IStream::ReadType()
+{
+ myLastType = BinTools_ObjectType (myStream->get());
+ myPosition++;
+ return myLastType;
+}
+
+//=======================================================================
+//function : IsReference
+//purpose :
+//=======================================================================
+Standard_Boolean BinTools_IStream::IsReference()
+{
+ return myLastType == BinTools_ObjectType_Reference8 || myLastType == BinTools_ObjectType_Reference16 ||
+ myLastType == BinTools_ObjectType_Reference32 || myLastType == BinTools_ObjectType_Reference64;
+}
+
+//=======================================================================
+//function : ReadReference
+//purpose :
+//=======================================================================
+uint64_t BinTools_IStream::ReadReference()
+{
+ uint64_t aDelta = 0;
+ uint64_t aCurrentPos = uint64_t (myStream->tellg());
+ switch (myLastType)
+ {
+ case BinTools_ObjectType_Reference8:
+ aDelta = uint64_t (myStream->get());
+ myPosition++;
+ break;
+ case BinTools_ObjectType_Reference16:
+ {
+ uint16_t aDelta16 = 0;
+ myStream->read ((char*)&aDelta16, sizeof (uint16_t));
+ myPosition += 2;
+#if DO_INVERSE
+ aDelta16 = (0 | ((aDelta16 & 0x00FF) << 8)
+ | ((aDelta16 & 0xFF00) >> 8));
+#endif
+ aDelta = uint64_t (aDelta16);
+ break;
+ }
+ case BinTools_ObjectType_Reference32:
+ {
+ uint32_t aDelta32 = 0;
+ myStream->read ((char*)&aDelta32, sizeof (uint32_t));
+ myPosition += 4;
+#if DO_INVERSE
+ aDelta32 = (0 | ((aDelta32 & 0x000000ff) << 24)
+ | ((aDelta32 & 0x0000ff00) << 8)
+ | ((aDelta32 & 0x00ff0000) >> 8)
+ | ((aDelta32 >> 24) & 0x000000ff));
+#endif
+ aDelta = uint64_t (aDelta32);
+ break;
+ }
+ case BinTools_ObjectType_Reference64:
+ myStream->read ((char*)&aDelta, sizeof (uint64_t));
+ myPosition += 8;
+#if DO_INVERSE
+ aDelta = InverseUint64 (aDelta);
+#endif
+ break;
+ default:
+ break;
+ }
+ if (aDelta == 0)
+ {
+ Standard_SStream aMsg;
+ aMsg << "BinTools_IStream::ReadReference: invalid reference " << (char)myLastType << std::endl;
+ throw Standard_Failure (aMsg.str().c_str());
+ }
+ return aCurrentPos - aDelta - 1; // add a type-byte
+}
+
+//=======================================================================
+//function : GoTo
+//purpose :
+//=======================================================================
+void BinTools_IStream::GoTo (const uint64_t& thePosition)
+{
+ myStream->seekg (std::streampos (thePosition));
+ myPosition = thePosition;
+}
+
+//=======================================================================
+//function : ShapeType
+//purpose :
+//=======================================================================
+TopAbs_ShapeEnum BinTools_IStream::ShapeType()
+{
+ return TopAbs_ShapeEnum ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) >> 2);
+}
+
+//=======================================================================
+//function : ShapeOrientation
+//purpose :
+//=======================================================================
+TopAbs_Orientation BinTools_IStream::ShapeOrientation()
+{
+ return TopAbs_Orientation ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) & 3);
+}
+
+//=======================================================================
+//function : operator bool
+//purpose :
+//=======================================================================
+BinTools_IStream::operator bool() const
+{
+ return *myStream ? Standard_True : Standard_False;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Real& theValue)
+{
+ if (!myStream->read ((char*)&theValue, sizeof (Standard_Real)))
+ throw Storage_StreamTypeMismatchError();
+ myPosition += sizeof (Standard_Real);
+#if DO_INVERSE
+ theValue = InverseReal (theValue);
+#endif
+ return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Integer& theValue)
+{
+ if (!myStream->read ((char*)&theValue, sizeof (Standard_Integer)))
+ throw Storage_StreamTypeMismatchError();
+ myPosition += sizeof (Standard_Integer);
+#if DO_INVERSE
+ theValue = InverseInt (theValue);
+#endif
+ return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (gp_Pnt& theValue)
+{
+ Standard_Real aValue;
+ for (int aCoord = 1; aCoord <= 3; aCoord++)
+ {
+ if (!myStream->read ((char*)&aValue, sizeof (Standard_Real)))
+ throw Storage_StreamTypeMismatchError();
+#if DO_INVERSE
+ aValue = InverseReal (aValue);
+#endif
+ theValue.SetCoord (aCoord, aValue);
+ }
+ myPosition += 3 * sizeof (Standard_Real);
+ return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Byte& theValue)
+{
+ myStream->read ((char*)&theValue, sizeof (Standard_Byte));
+ myPosition += sizeof (Standard_Byte);
+ return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_ShortReal& theValue)
+{
+ myStream->read ((char*)&theValue, sizeof (Standard_ShortReal));
+ myPosition += sizeof (Standard_ShortReal);
+ return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose :
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (gp_Trsf& theValue)
+{
+ Standard_Real aV1[3], aV2[3], aV3[3], aV[3];
+ *this >> aV1[0] >> aV1[1] >> aV1[2] >> aV[0];
+ *this >> aV2[0] >> aV2[1] >> aV2[2] >> aV[1];
+ *this >> aV3[0] >> aV3[1] >> aV3[2] >> aV[2];
+ theValue.SetValues (aV1[0], aV1[1], aV1[2], aV[0],
+ aV2[0], aV2[1], aV2[2], aV[1],
+ aV3[0], aV3[1], aV3[2], aV[2]);
+ return *this;
+}
+
+//=======================================================================
+//function : ReadBools
+//purpose :
+//=======================================================================
+void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3)
+{
+ Standard_Byte aByte = ReadByte();
+ theBool1 = (aByte & 1) == 1;
+ theBool2 = (aByte & 2) == 2;
+ theBool3 = (aByte & 4) == 4;
+}
+
+//=======================================================================
+//function : ReadBools
+//purpose :
+//=======================================================================
+void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3,
+ Standard_Boolean& theBool4, Standard_Boolean& theBool5, Standard_Boolean& theBool6, Standard_Boolean& theBool7)
+{
+ Standard_Byte aByte = ReadByte();
+ theBool1 = (aByte & 1) == 1;
+ theBool2 = (aByte & 2) == 2;
+ theBool3 = (aByte & 4) == 4;
+ theBool4 = (aByte & 8) == 8;
+ theBool5 = (aByte & 16) == 16;
+ theBool6 = (aByte & 32) == 32;
+ theBool7 = (aByte & 64) == 64;
+}