/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2016, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Teigha(R) software pursuant to a license // agreement with Open Design Alliance. // Teigha(R) Copyright (C) 2002-2016 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _OD_PLATFORMSTREAMER_H_ #define _OD_PLATFORMSTREAMER_H_ #include "OdPlatform.h" #include "OdStreamBuf.h" #include "DbHandle.h" #include "OdString.h" /** \details This class implements platform dependent stream I/O for various data types. */ class OdPlatformStreamer { public: /** \details Reads a 16-bit integer from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static OdInt16 rdInt16 (OdStreamBuf& streamBuf); /** \details Reads a 32-bit integer from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static OdInt32 rdInt32 (OdStreamBuf& streamBuf); /** \details Reads a 64-bit integer from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static OdInt64 rdInt64 (OdStreamBuf& streamBuf); /** \details Reads a 32-bit floating point number from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static float rdFloat (OdStreamBuf& streamBuf); /** \details Reads a double from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static double rdDouble (OdStreamBuf& streamBuf); /** \details Reads a handle from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. */ static OdDbHandle rdDbHandle(OdStreamBuf& streamBuf); /** \details Reads two doubles from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. \param doubles [out] Array of doubles to receive the data. */ static void rd2Doubles(OdStreamBuf& streamBuf, void* doubles); /** \details Reads three doubles from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. \param doubles [out] Array of doubles to receive the data. */ static void rd3Doubles(OdStreamBuf& streamBuf, void* doubles); /** \details Reads the specified number of doubles from the specified StreamBuf object. \param streamBuf [in] StreamBuf object from which the data are to be read. \param doubles [out] Array of doubles to receive the data. \param numDoubles [in] Number of doubles. */ static void rdDoubles (OdStreamBuf& streamBuf, int numDoubles, void* doubles); /** \details Writes a 16-bit integer to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrInt16 (OdStreamBuf& streamBuf, OdInt16 value); /** \details Writes a 32-bit integer to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrInt32 (OdStreamBuf& streamBuf, OdInt32 value); /** \details Writes a 64-bit integer to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrInt64 (OdStreamBuf& streamBuf, OdInt64 value); /** \details Writes a 32-bit floating point number to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrFloat (OdStreamBuf& out, float val); /** \details Writes a double to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrDouble (OdStreamBuf& streamBuf, double value); /** \details Writes a handle to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param value [in] Value to be written. */ static void wrDbHandle(OdStreamBuf& streamBuf, OdDbHandle value); /** \details Writes two doubles to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param doubles [in] Array of doubles to be written. */ static void wr2Doubles(OdStreamBuf& streamBuf, const void* doubles); /** \details Writes three doubles to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param doubles [in] Array of doubles to be written. */ static void wr3Doubles(OdStreamBuf& streamBuf, const void* doubles); /** \details Writes the specified number of doubles to the specified StreamBuf object. \param streamBuf [out] StreamBuf object to which the data are to be written. \param doubles [in] Array of doubles to be written. \param numDoubles [in] Number of doubles. */ static void wrDoubles (OdStreamBuf& streamBuf, int numDoubles, const void* doubles); /** \details Extracts a Unicode string from buffer, and returns it as an OdString. \param buffer [in/out] Buffer pointer to read the Unicode string from. \param size [in] Length of the Unicode string in characters (assumes 2 byte characters in buffer stored in little endian format), or -1 if the string is null terminated. \remarks The buffer pointer is incremented to the next byte past the string that was read in. If size is > 0, size * 2 bytes will be read. If size is -1, a null terminated string will be read from buffer, including the null byte. */ inline static OdString getUnicodeStrFromBuffer(const OdUInt8*& buffer, OdInt32 size); /** \details Writes a Unicode string to the passed in buffer, in little endian format, using 2 bytes per character. The trailing null character is NOT written. \param val [in] Unicode string to be written. \param buffer [in] Char buffer to which will receive the Unicode data. \remarks The buffer pointer is incremented to the next byte past the string that was written. */ inline static void putUnicodeStrToBuffer(const OdString& val, OdUInt8*& buffer); }; inline OdInt16 OdPlatformStreamer::rdInt16(OdStreamBuf& streamBuf) { OdInt16 res; streamBuf.getBytes(&res, sizeof(res)); odSwap2BytesNumber(res); return res; } inline OdInt32 OdPlatformStreamer::rdInt32(OdStreamBuf& streamBuf) { OdInt32 res; streamBuf.getBytes(&res, sizeof(res)); odSwap4BytesNumber(res); return res; } inline OdInt64 OdPlatformStreamer::rdInt64(OdStreamBuf& streamBuf) { OdInt64 res; streamBuf.getBytes(&res, sizeof(res)); odSwap8Bytes(&res); return res; } inline float OdPlatformStreamer::rdFloat(OdStreamBuf& streamBuf) { float res; streamBuf.getBytes(&res, sizeof(res)); odSwap4Bytes(&res); return res; } inline double OdPlatformStreamer::rdDouble(OdStreamBuf& streamBuf) { double res; ODA_ASSUME(sizeof(res) == 8) streamBuf.getBytes(&res, 8); odSwap8Bytes(&res); // if unnormalized or NaN or infinity, set it to 0.0 if (!isValidNonZeroIEEEDouble((OdUInt8 *)&res)) return 0.0; return res; } inline OdDbHandle OdPlatformStreamer::rdDbHandle(OdStreamBuf& streamBuf) { OdDbHandle res; ODA_ASSUME(sizeof(res) == 8) streamBuf.getBytes(&res, 8); odSwapInt64(&res); return res; } inline void OdPlatformStreamer::rd2Doubles(OdStreamBuf& streamBuf, void* pRes2Doubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.getBytes(pRes2Doubles, sizeof(double)*2); fixDouble((double*)pRes2Doubles); fixDouble((double*)pRes2Doubles+1); } inline void OdPlatformStreamer::rd3Doubles(OdStreamBuf& streamBuf, void* pRes3Doubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.getBytes(pRes3Doubles, sizeof(double)*3); fixDouble((double*)pRes3Doubles); fixDouble((double*)pRes3Doubles+1); fixDouble((double*)pRes3Doubles+2); } inline void OdPlatformStreamer::rdDoubles(OdStreamBuf& streamBuf, int n, void* pResDoubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.getBytes(pResDoubles, sizeof(double)*n); double* pD = (double*)pResDoubles; while (n--) { fixDouble(pD++); } } inline void OdPlatformStreamer::wrInt16(OdStreamBuf& streamBuf, OdInt16 val) { odSwap2BytesNumber(val); streamBuf.putBytes(&val, sizeof(val)); } inline void OdPlatformStreamer::wrInt32(OdStreamBuf& streamBuf, OdInt32 val) { odSwap4BytesNumber(val); streamBuf.putBytes(&val, sizeof(val)); } inline void OdPlatformStreamer::wrInt64(OdStreamBuf& streamBuf, OdInt64 val) { odSwap8Bytes(&val); streamBuf.putBytes(&val, sizeof(val)); } inline void OdPlatformStreamer::wrFloat(OdStreamBuf& streamBuf, float val) { odSwap4Bytes(&val); streamBuf.putBytes(&val, sizeof(val)); } inline void OdPlatformStreamer::wrDouble(OdStreamBuf& streamBuf, double val) { ODA_ASSUME(sizeof(double) == 8) odSwap8Bytes(&val); streamBuf.putBytes(&val, sizeof(val)); } inline void OdPlatformStreamer::wrDbHandle(OdStreamBuf& streamBuf, OdDbHandle val) { odSwapInt64(&val); streamBuf.putBytes(&val, sizeof(val)); } inline OdString OdPlatformStreamer::getUnicodeStrFromBuffer(const OdUInt8*& buffer, OdInt32 size) { OdString ret; #if ODCHAR_IS_INT16LE if (size == -1) { // null terminated ret = (OdChar*)buffer; buffer += ((ret.getLength() + 1) * 2); } else { OdUInt8* pBuf = (OdUInt8*)ret.getBuffer(size+1); OD_BYTES_FROM_BUFFPTR(buffer, pBuf, (size<<1)); ret.releaseBuffer(size); } #else OdInt32 finalSize = size; if (size == -1) { // null terminated size = 1; OdUInt16* tmp16 = (OdUInt16*)buffer; for ( ; *tmp16; tmp16++) size++; finalSize = size - 1; } OdChar* pBuf = ret.getBuffer(size + 1); for (OdInt32 i = 0; i < size; i++) { *pBuf++ = OdUInt16(OD_INT16_FROM_BUFFPTR(buffer)); } *pBuf = L'\0'; ret.releaseBuffer(finalSize); #endif return ret; } #ifndef ODCHAR_IS_INT16LE #error "OdaDefs.h must be included before OdPlatformStreamer.h" #endif void OdPlatformStreamer::putUnicodeStrToBuffer(const OdString& val, OdUInt8*& buffer) { OdInt32 nLen = val.getLength(); #if ODCHAR_IS_INT16LE OD_BYTES_TO_BUFFPTR(buffer, val.c_str(), nLen*sizeof(OdChar)); #else const OdChar* p = val.c_str(); for (OdUInt32 i = 0; i < nLen; i++) { OD_INT16_TO_BUFFPTR(buffer, (OdInt16)*p++); } #endif } // Verify that preprocessor symbol ODCHAR_IS_INT16LE has been correctly defined #if ODCHAR_IS_INT16LE #ifdef ODA_BIGENDIAN #error "ODCHAR_IS_INT16LE is defined for a big endian platform" #endif ODA_ASSUME(sizeof(OdChar) == 2); #endif #ifdef ODA_BIGENDIAN inline void OdPlatformStreamer::wr2Doubles(OdStreamBuf& streamBuf, const void* p2Doubles) { wrDouble(streamBuf, *(((double*)p2Doubles)+0)); wrDouble(streamBuf, *(((double*)p2Doubles)+1)); } inline void OdPlatformStreamer::wr3Doubles(OdStreamBuf& streamBuf, const void* p3Doubles) { wrDouble(streamBuf, *(((double*)p3Doubles)+0)); wrDouble(streamBuf, *(((double*)p3Doubles)+1)); wrDouble(streamBuf, *(((double*)p3Doubles)+2)); } inline void OdPlatformStreamer::wrDoubles(OdStreamBuf& streamBuf, int n, const void* pDoubles) { while(n--) wrDouble(streamBuf, ((double*)pDoubles)[n]); } #else // #ifdef ODA_BIGENDIAN inline void OdPlatformStreamer::wr2Doubles(OdStreamBuf& streamBuf, const void* p2Doubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.putBytes(p2Doubles, sizeof(double)*2); } inline void OdPlatformStreamer::wr3Doubles(OdStreamBuf& streamBuf, const void* p3Doubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.putBytes(p3Doubles, sizeof(double)*3); } inline void OdPlatformStreamer::wrDoubles(OdStreamBuf& streamBuf, int n, const void* pDoubles) { ODA_ASSUME(sizeof(double) == 8) streamBuf.putBytes(pDoubles, sizeof(double) * n); } #endif // ODA_BIGENDIAN #endif // _OD_PLATFORMSTREAMER_H_