1 /***************************************************************************
2                              qgsogrutils.h
3                              -------------
4     begin                : February 2016
5     copyright            : (C) 2016 Nyall Dawson
6     email                : nyall dot dawson at gmail dot com
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 
16 #ifndef QGSOGRUTILS_H
17 #define QGSOGRUTILS_H
18 
19 #define SIP_NO_FILE
20 
21 #include "qgis_core.h"
22 #include "qgsfeature.h"
23 
24 #include <ogr_api.h>
25 #include <gdal.h>
26 #include <gdalwarper.h>
27 #include "cpl_conv.h"
28 #include "cpl_string.h"
29 
30 namespace gdal
31 {
32 
33   /**
34    * Destroys OGR data sources.
35    */
36   struct OGRDataSourceDeleter
37   {
38 
39     /**
40      * Destroys an OGR data \a source, using the correct gdal calls.
41      */
42     void CORE_EXPORT operator()( OGRDataSourceH source );
43 
44   };
45 
46   /**
47    * Destroys OGR geometries.
48    */
49   struct OGRGeometryDeleter
50   {
51 
52     /**
53      * Destroys an OGR \a geometry, using the correct gdal calls.
54      */
55     void CORE_EXPORT operator()( OGRGeometryH geometry );
56 
57   };
58 
59   /**
60    * Destroys OGR field definition.
61    */
62   struct OGRFldDeleter
63   {
64 
65     /**
66      * Destroys an OGR field \a definition, using the correct gdal calls.
67      */
68     void CORE_EXPORT operator()( OGRFieldDefnH definition );
69 
70   };
71 
72   /**
73    * Destroys OGR feature.
74    */
75   struct OGRFeatureDeleter
76   {
77 
78     /**
79      * Destroys an OGR \a feature, using the correct gdal calls.
80      */
81     void CORE_EXPORT operator()( OGRFeatureH feature );
82 
83   };
84 
85   /**
86    * Closes and cleanups GDAL dataset.
87    */
88   struct GDALDatasetCloser
89   {
90 
91     /**
92      * Destroys an gdal \a dataset, using the correct gdal calls.
93      */
94     void CORE_EXPORT operator()( GDALDatasetH datasource );
95 
96   };
97 
98   /**
99    * Closes and cleanups GDAL warp options.
100    */
101   struct GDALWarpOptionsDeleter
102   {
103 
104     /**
105      * Destroys GDAL warp \a options, using the correct gdal calls.
106      */
107     void CORE_EXPORT operator()( GDALWarpOptions *options );
108 
109   };
110 
111   /**
112    * Scoped OGR data source.
113    */
114   using ogr_datasource_unique_ptr = std::unique_ptr< std::remove_pointer<OGRDataSourceH>::type, OGRDataSourceDeleter >;
115 
116   /**
117    * Scoped OGR geometry.
118    */
119   using ogr_geometry_unique_ptr = std::unique_ptr< std::remove_pointer<OGRGeometryH>::type, OGRGeometryDeleter >;
120 
121   /**
122    * Scoped OGR field definition.
123    */
124   using ogr_field_def_unique_ptr = std::unique_ptr< std::remove_pointer<OGRFieldDefnH>::type, OGRFldDeleter >;
125 
126   /**
127    * Scoped OGR feature.
128    */
129   using ogr_feature_unique_ptr = std::unique_ptr< std::remove_pointer<OGRFeatureH>::type, OGRFeatureDeleter >;
130 
131   /**
132    * Scoped GDAL dataset.
133    */
134   using dataset_unique_ptr = std::unique_ptr< std::remove_pointer<GDALDatasetH>::type, GDALDatasetCloser >;
135 
136   /**
137    * Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying
138    * data store. Use when the resultant dataset is no longer required, e.g. as a result
139    * of user cancellation of an operation.
140    *
141    * Requires a gdal \a dataset pointer, the corresponding gdal \a driver and underlying
142    * dataset file \a path.
143    */
144   void CORE_EXPORT fast_delete_and_close( dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path );
145 
146   /**
147    * Scoped GDAL warp options.
148    */
149   using warp_options_unique_ptr = std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter >;
150 }
151 
152 /**
153  * \ingroup core
154  * \class QgsOgrUtils
155  * \brief Utilities for working with OGR features and layers
156  *
157  * Contains helper utilities for assisting work with both OGR features and layers.
158  * \note not available in Python bindings
159  * \since QGIS 2.16
160  */
161 class CORE_EXPORT QgsOgrUtils
162 {
163   public:
164 
165     /**
166      * Reads an OGR feature and converts it to a QgsFeature.
167      * \param ogrFet OGR feature handle
168      * \param fields fields collection corresponding to feature
169      * \param encoding text encoding
170      * \returns valid feature if read was successful
171      */
172     static QgsFeature readOgrFeature( OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding );
173 
174     /**
175      * Reads an OGR feature and returns a corresponding fields collection.
176      * \param ogrFet OGR feature handle
177      * \param encoding text encoding
178      * \returns fields collection if read was successful
179      */
180     static QgsFields readOgrFields( OGRFeatureH ogrFet, QTextCodec *encoding );
181 
182     /**
183      * Retrieves an attribute value from an OGR feature.
184      * \param ogrFet OGR feature handle
185      * \param fields fields collection corresponding to feature
186      * \param attIndex index of attribute to retrieve
187      * \param encoding text encoding
188      * \param ok optional storage for success of retrieval
189      * \returns attribute converted to a QVariant object
190      * \see readOgrFeatureAttributes()
191      */
192     static QVariant getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok = nullptr );
193 
194     /**
195      * Retrieves an attribute value from an OGR feature, using a provided \a field definition.
196      * \param ogrFet OGR feature handle
197      * \param field definition of corresponding field
198      * \param attIndex index of attribute to retrieve from \a ogrFet
199      * \param encoding text encoding
200      * \param ok optional storage for success of retrieval
201      * \returns attribute converted to a QVariant object
202      * \see readOgrFeatureAttributes()
203      *
204      * \since QGIS 3.10.1
205      */
206     static QVariant getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsField &field, int attIndex, QTextCodec *encoding, bool *ok = nullptr );
207 
208     /**
209      * Reads all attributes from an OGR feature into a QgsFeature.
210      * \param ogrFet OGR feature handle
211      * \param fields fields collection corresponding to feature
212      * \param feature QgsFeature to store attributes in
213      * \param encoding text encoding
214      * \returns TRUE if attribute read was successful
215      * \see getOgrFeatureAttribute()
216      */
217     static bool readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding );
218 
219     /**
220      * Reads the geometry from an OGR feature into a QgsFeature.
221      * \param ogrFet OGR feature handle
222      * \param feature QgsFeature to store geometry in
223      * \returns TRUE if geometry read was successful
224      * \see readOgrFeatureAttributes()
225      * \see ogrGeometryToQgsGeometry()
226      */
227     static bool readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature &feature );
228 
229     /**
230      * Converts an OGR geometry representation to a QgsGeometry object
231      * \param geom OGR geometry handle
232      * \returns QgsGeometry object. If conversion was not successful the geometry
233      * will be empty.
234      * \see readOgrFeatureGeometry()
235      */
236     static QgsGeometry ogrGeometryToQgsGeometry( OGRGeometryH geom );
237 
238     /**
239      * Attempts to parse a string representing a collection of features using OGR. For example, this method can be
240      * used to convert a GeoJSON encoded collection to a list of QgsFeatures.
241      * \param string string to parse
242      * \param fields fields collection to use for parsed features (\see stringToFields())
243      * \param encoding text encoding
244      * \returns list of parsed features, or an empty list if no features could be parsed
245      * \see stringToFields()
246      */
247     static QgsFeatureList stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding );
248 
249     /**
250      * Attempts to retrieve the fields from a string representing a collection of features using OGR.
251      * \param string string to parse
252      * \param encoding text encoding
253      * \returns retrieved fields collection, or an empty list if no fields could be determined from the string
254      * \see stringToFeatureList()
255      */
256     static QgsFields stringToFields( const QString &string, QTextCodec *encoding );
257 
258     /**
259      * Converts a c string list to a QStringList. Presumes a null terminated string list.
260      *
261      * \since QGIS 3.2
262      */
263     static QStringList cStringListToQStringList( char **stringList );
264 
265     /**
266      * Converts a OGRwkbGeometryType to QgsWkbTypes::Type
267      *
268      * \since QGIS 3.4.9
269      */
270     static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType( OGRwkbGeometryType ogrGeomType );
271 
272     /**
273      * Returns a WKT string corresponding to the specified OGR \a srs object.
274      *
275      * The WKT string format will be selected using the most appropriate format (usually WKT2 if GDAL 3 is available).
276      *
277      * \since QGIS 3.10.1
278      */
279     static QString OGRSpatialReferenceToWkt( OGRSpatialReferenceH srs );
280 
281     /**
282      * Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR \a srs object, or an invalid
283      * QgsCoordinateReferenceSystem if \a srs could not be converted.
284      *
285      * \since QGIS 3.10.1
286      */
287     static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs( OGRSpatialReferenceH srs );
288 
289     /**
290      * Reads the encoding of the shapefile at the specified \a path (where \a path is the
291      * location of the ".shp" file).
292      *
293      * This method considers both the CPG specified encoding and the DBF LDID encoding
294      * (priority goes to CPG based encoding)
295      *
296      * \see readShapefileEncodingFromCpg()
297      * \see readShapefileEncodingFromLdid()
298      * \since QGIS 3.12
299      */
300     static QString readShapefileEncoding( const QString &path );
301 
302     /**
303      * Reads the encoding of the shapefile at the specified \a path (where \a path is the
304      * location of the ".shp" file), from the CPG specified encoding.
305      *
306      * Return an empty string if CPG based encoding was not found.
307      *
308      * \see readShapefileEncoding()
309      * \since QGIS 3.12
310      */
311     static QString readShapefileEncodingFromCpg( const QString &path );
312 
313     /**
314      * Reads the encoding of the shapefile at the specified \a path (where \a path is the
315      * location of the ".shp" file), from the DBF LDID encoding.
316      *
317      * Return an empty string if LDID based encoding was not found.
318      *
319      * \see readShapefileEncoding()
320      * \since QGIS 3.12
321      */
322     static QString readShapefileEncodingFromLdid( const QString &path );
323 };
324 
325 #endif // QGSOGRUTILS_H
326