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