1 /*************************************************************************** 2 qgswkbptr.h 3 --------------------- 4 begin : January 2014 5 copyright : (C) 2014 by Juergen E. Fischer 6 email : jef at norbit dot de 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 #ifndef QGSWKBPTR_H 16 #define QGSWKBPTR_H 17 18 #include "qgis_core.h" 19 #include "qgswkbtypes.h" 20 #include "qgis_sip.h" 21 #include "qgsexception.h" 22 #include "qpolygon.h" 23 24 /** 25 * \ingroup core 26 * \brief Custom exception class for Wkb related exceptions. 27 * \note not available in Python bindings 28 */ 29 #ifndef SIP_RUN 30 class CORE_EXPORT QgsWkbException : public QgsException 31 { 32 public: QgsWkbException(QString const & what)33 QgsWkbException( QString const &what ) : QgsException( what ) {} 34 }; 35 #endif 36 37 38 /** 39 * \ingroup core 40 * \class QgsWkbPtr 41 * \brief WKB pointer handler. 42 */ 43 class CORE_EXPORT QgsWkbPtr 44 { 45 mutable unsigned char *mP; 46 unsigned char *mStart; 47 unsigned char *mEnd; 48 49 void verifyBound( int size ) const; 50 read(T & v)51 template<typename T> void read( T &v ) const 52 { 53 verifyBound( sizeof v ); 54 memcpy( &v, mP, sizeof v ); 55 mP += sizeof v; 56 } 57 write(T & v)58 template<typename T> void write( T &v ) const 59 { 60 verifyBound( sizeof v ); 61 memcpy( mP, &v, sizeof v ); 62 mP += sizeof v; 63 } 64 write(const QByteArray & data)65 void write( const QByteArray &data ) const 66 { 67 verifyBound( data.length() ); 68 memcpy( mP, data.constData(), data.length() ); 69 mP += data.length(); 70 } 71 72 public: 73 //! Construct WKB pointer from QByteArray 74 QgsWkbPtr( QByteArray &wkb ) SIP_SKIP; 75 76 QgsWkbPtr( unsigned char *p SIP_ARRAY, int size SIP_ARRAYSIZE ); 77 78 inline const QgsWkbPtr &operator>>( double &v ) const { read( v ); return *this; } SIP_SKIP 79 inline const QgsWkbPtr &operator>>( float &r ) const { double v; read( v ); r = v; return *this; } SIP_SKIP 80 inline const QgsWkbPtr &operator>>( int &v ) const { read( v ); return *this; } SIP_SKIP 81 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 82 //! Reads an integer value into a qsizetype 83 inline const QgsWkbPtr &operator>>( qsizetype &r ) const { int v; read( v ); r = v; return *this; } SIP_SKIP 84 #endif 85 inline const QgsWkbPtr &operator>>( unsigned int &v ) const { read( v ); return *this; } SIP_SKIP 86 inline const QgsWkbPtr &operator>>( char &v ) const { read( v ); return *this; } SIP_SKIP 87 inline const QgsWkbPtr &operator>>( QgsWkbTypes::Type &v ) const { read( v ); return *this; } SIP_SKIP 88 89 //! Writes a double to the pointer 90 inline QgsWkbPtr &operator<<( double v ) { write( v ); return *this; } SIP_SKIP 91 //! Writes a float to the pointer 92 inline QgsWkbPtr &operator<<( float r ) { double v = r; write( v ); return *this; } SIP_SKIP 93 //! Writes an int to the pointer 94 inline QgsWkbPtr &operator<<( int v ) { write( v ); return *this; } SIP_SKIP 95 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 96 //! Writes a size as int to the pointer 97 inline QgsWkbPtr &operator<<( qsizetype r ) { int v = r; write( v ); return *this; } SIP_SKIP 98 #endif 99 //! Writes an unsigned int to the pointer 100 inline QgsWkbPtr &operator<<( unsigned int v ) { write( v ); return *this; } SIP_SKIP 101 //! Writes a char to the pointer 102 inline QgsWkbPtr &operator<<( char v ) { write( v ); return *this; } SIP_SKIP 103 //! Writes a WKB type value to the pointer 104 inline QgsWkbPtr &operator<<( QgsWkbTypes::Type v ) { write( v ); return *this; } SIP_SKIP 105 //! Append data from a byte array 106 inline QgsWkbPtr &operator<<( const QByteArray &data ) { write( data ); return *this; } SIP_SKIP 107 108 inline void operator+=( int n ) { verifyBound( n ); mP += n; } SIP_SKIP 109 110 inline operator unsigned char *() const { return mP; } SIP_SKIP 111 112 /** 113 * \brief size 114 * \note not available in Python bindings 115 */ size()116 inline int size() const { return mEnd - mStart; } SIP_SKIP 117 118 /** 119 * \brief remaining 120 * \note not available in Python bindings 121 */ remaining()122 inline int remaining() const { return mEnd - mP; } SIP_SKIP 123 124 /** 125 * \brief writtenSize 126 * \note not available in Python bindings 127 */ writtenSize()128 inline int writtenSize() const { return mP - mStart; } SIP_SKIP 129 }; 130 131 /** 132 * \ingroup core 133 * \class QgsConstWkbPtr 134 * \brief A const WKB pointer. 135 */ 136 137 class CORE_EXPORT QgsConstWkbPtr 138 { 139 protected: 140 mutable unsigned char *mP; 141 unsigned char *mEnd; 142 mutable bool mEndianSwap; 143 mutable QgsWkbTypes::Type mWkbType; 144 145 /** 146 * \brief Verify bounds 147 * \note not available in Python bindings 148 */ 149 void verifyBound( int size ) const SIP_SKIP; 150 151 /** 152 * \brief Read a value 153 * \note not available in Python bindings 154 */ read(T & v)155 template<typename T> void read( T &v ) const SIP_SKIP 156 { 157 verifyBound( sizeof v ); 158 memcpy( &v, mP, sizeof( v ) ); 159 mP += sizeof( v ); 160 if ( mEndianSwap ) 161 endian_swap( v ); 162 } 163 164 public: 165 //! Construct WKB pointer from QByteArray 166 explicit QgsConstWkbPtr( const QByteArray &wkb ) SIP_SKIP; 167 QgsConstWkbPtr( const unsigned char *p SIP_ARRAY, int size SIP_ARRAYSIZE ); 168 169 /** 170 * \brief readHeader 171 * \note not available in Python bindings 172 */ 173 QgsWkbTypes::Type readHeader() const SIP_SKIP; 174 175 inline const QgsConstWkbPtr &operator>>( double &v ) const { read( v ); return *this; } SIP_SKIP 176 inline const QgsConstWkbPtr &operator>>( float &r ) const { double v; read( v ); r = v; return *this; } SIP_SKIP 177 inline const QgsConstWkbPtr &operator>>( int &v ) const { read( v ); return *this; } SIP_SKIP 178 inline const QgsConstWkbPtr &operator>>( unsigned int &v ) const { read( v ); return *this; } SIP_SKIP 179 inline const QgsConstWkbPtr &operator>>( char &v ) const { read( v ); return *this; } SIP_SKIP 180 181 //! Read a point 182 const QgsConstWkbPtr &operator>>( QPointF &point ) const; SIP_SKIP 183 //! Read a point array 184 const QgsConstWkbPtr &operator>>( QPolygonF &points ) const; SIP_SKIP 185 186 inline void operator+=( int n ) { verifyBound( n ); mP += n; } SIP_SKIP 187 inline void operator-=( int n ) { mP -= n; } SIP_SKIP 188 189 inline operator const unsigned char *() const { return mP; } SIP_SKIP 190 191 /** 192 * \brief remaining 193 * \note not available in Python bindings 194 */ remaining()195 inline int remaining() const { return mEnd - mP; } SIP_SKIP 196 197 private: endian_swap(T & value)198 template<typename T> void endian_swap( T &value ) const SIP_SKIP 199 { 200 char *data = reinterpret_cast<char *>( &value ); 201 const std::size_t n = sizeof( value ); 202 for ( std::size_t i = 0, m = n / 2; i < m; ++i ) 203 { 204 std::swap( data[i], data[n - 1 - i] ); 205 } 206 } 207 }; 208 209 #endif // QGSWKBPTR_H 210