QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsogrutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsogrutils.cpp
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 #include "qgsogrutils.h"
17 #include "qgsapplication.h"
18 #include "qgslogger.h"
19 #include "qgsgeometry.h"
20 #include "qgsfields.h"
21 #include "qgslinestring.h"
22 #include "qgsmultipoint.h"
23 #include <QTextCodec>
24 #include <QUuid>
25 #include <cpl_error.h>
26 
27 // Starting with GDAL 2.2, there are 2 concepts: unset fields and null fields
28 // whereas previously there was only unset fields. For QGIS purposes, both
29 // states (unset/null) are equivalent.
30 #ifndef OGRNullMarker
31 #define OGR_F_IsFieldSetAndNotNull OGR_F_IsFieldSet
32 #endif
33 
34 
35 
36 void gdal::OGRDataSourceDeleter::operator()( OGRDataSourceH source )
37 {
38  OGR_DS_Destroy( source );
39 }
40 
41 
42 void gdal::OGRGeometryDeleter::operator()( OGRGeometryH geometry )
43 {
44  OGR_G_DestroyGeometry( geometry );
45 }
46 
47 void gdal::OGRFldDeleter::operator()( OGRFieldDefnH definition )
48 {
49  OGR_Fld_Destroy( definition );
50 }
51 
52 void gdal::OGRFeatureDeleter::operator()( OGRFeatureH feature )
53 {
54  OGR_F_Destroy( feature );
55 }
56 
58 {
59  GDALClose( dataset );
60 }
61 
62 void gdal::fast_delete_and_close( gdal::dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path )
63 {
64  // see https://github.com/qgis/QGIS/commit/d024910490a39e65e671f2055c5b6543e06c7042#commitcomment-25194282
65  // faster if we close the handle AFTER delete, but doesn't work for windows
66 #ifdef Q_OS_WIN
67  // close dataset handle
68  dataset.reset();
69 #endif
70 
71  CPLPushErrorHandler( CPLQuietErrorHandler );
72  GDALDeleteDataset( driver, path.toUtf8().constData() );
73  CPLPopErrorHandler();
74 
75 #ifndef Q_OS_WIN
76  // close dataset handle
77  dataset.reset();
78 #endif
79 }
80 
81 
82 void gdal::GDALWarpOptionsDeleter::operator()( GDALWarpOptions *options )
83 {
84  GDALDestroyWarpOptions( options );
85 }
86 
87 QgsFeature QgsOgrUtils::readOgrFeature( OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding )
88 {
89  QgsFeature feature;
90  if ( !ogrFet )
91  {
92  feature.setValid( false );
93  return feature;
94  }
95 
96  feature.setId( OGR_F_GetFID( ogrFet ) );
97  feature.setValid( true );
98 
99  if ( !readOgrFeatureGeometry( ogrFet, feature ) )
100  {
101  feature.setValid( false );
102  }
103 
104  if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
105  {
106  feature.setValid( false );
107  }
108 
109  return feature;
110 }
111 
112 QgsFields QgsOgrUtils::readOgrFields( OGRFeatureH ogrFet, QTextCodec *encoding )
113 {
114  QgsFields fields;
115 
116  if ( !ogrFet )
117  return fields;
118 
119  int fieldCount = OGR_F_GetFieldCount( ogrFet );
120  for ( int i = 0; i < fieldCount; ++i )
121  {
122  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
123  if ( !fldDef )
124  {
125  fields.append( QgsField() );
126  continue;
127  }
128 
129  QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
130  QVariant::Type varType;
131  switch ( OGR_Fld_GetType( fldDef ) )
132  {
133  case OFTInteger:
134  if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
135  varType = QVariant::Bool;
136  else
137  varType = QVariant::Int;
138  break;
139  case OFTInteger64:
140  varType = QVariant::LongLong;
141  break;
142  case OFTReal:
143  varType = QVariant::Double;
144  break;
145  case OFTDate:
146  varType = QVariant::Date;
147  break;
148  case OFTTime:
149  varType = QVariant::Time;
150  break;
151  case OFTDateTime:
152  varType = QVariant::DateTime;
153  break;
154  case OFTString:
155  default:
156  varType = QVariant::String; // other unsupported, leave it as a string
157  }
158  fields.append( QgsField( name, varType ) );
159  }
160  return fields;
161 }
162 
163 QVariant QgsOgrUtils::getOgrFeatureAttribute( OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok )
164 {
165  if ( !ogrFet || attIndex < 0 || attIndex >= fields.count() )
166  {
167  if ( ok )
168  *ok = false;
169  return QVariant();
170  }
171 
172  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
173 
174  if ( ! fldDef )
175  {
176  if ( ok )
177  *ok = false;
178 
179  QgsDebugMsg( QStringLiteral( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
180  return QVariant();
181  }
182 
183  QVariant value;
184 
185  if ( ok )
186  *ok = true;
187 
188  if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
189  {
190  switch ( fields.at( attIndex ).type() )
191  {
192  case QVariant::String:
193  {
194  if ( encoding )
195  value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
196  else
197  value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
198  break;
199  }
200  case QVariant::Int:
201  value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
202  break;
203  case QVariant::Bool:
204  value = QVariant( bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
205  break;
206  case QVariant::LongLong:
207  value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
208  break;
209  case QVariant::Double:
210  value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
211  break;
212  case QVariant::Date:
213  case QVariant::DateTime:
214  case QVariant::Time:
215  {
216  int year, month, day, hour, minute, second, tzf;
217 
218  OGR_F_GetFieldAsDateTime( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
219  if ( fields.at( attIndex ).type() == QVariant::Date )
220  value = QDate( year, month, day );
221  else if ( fields.at( attIndex ).type() == QVariant::Time )
222  value = QTime( hour, minute, second );
223  else
224  value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) );
225  }
226  break;
227  default:
228  Q_ASSERT_X( false, "QgsOgrUtils::getOgrFeatureAttribute", "unsupported field type" );
229  if ( ok )
230  *ok = false;
231  }
232  }
233  else
234  {
235  value = QVariant( QString() );
236  }
237 
238  return value;
239 }
240 
241 bool QgsOgrUtils::readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding )
242 {
243  // read all attributes
244  feature.initAttributes( fields.count() );
245  feature.setFields( fields );
246 
247  if ( !ogrFet )
248  return false;
249 
250  bool ok = false;
251  for ( int idx = 0; idx < fields.count(); ++idx )
252  {
253  QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
254  if ( ok )
255  {
256  feature.setAttribute( idx, value );
257  }
258  }
259  return true;
260 }
261 
262 bool QgsOgrUtils::readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature &feature )
263 {
264  if ( !ogrFet )
265  return false;
266 
267  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
268  if ( !geom )
269  feature.clearGeometry();
270  else
271  feature.setGeometry( ogrGeometryToQgsGeometry( geom ) );
272 
273  return true;
274 }
275 
276 std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint( OGRGeometryH geom )
277 {
278  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
279 
280  double x, y, z, m;
281  OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
282  return qgis::make_unique< QgsPoint >( wkbType, x, y, z, m );
283 }
284 
285 std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint( OGRGeometryH geom )
286 {
287  std::unique_ptr< QgsMultiPoint > mp = qgis::make_unique< QgsMultiPoint >();
288 
289  const int count = OGR_G_GetGeometryCount( geom );
290  for ( int i = 0; i < count; ++i )
291  {
292  mp->addGeometry( ogrGeometryToQgsPoint( OGR_G_GetGeometryRef( geom, i ) ).release() );
293  }
294 
295  return mp;
296 }
297 
298 std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString( OGRGeometryH geom )
299 {
300  QgsWkbTypes::Type wkbType = static_cast<QgsWkbTypes::Type>( OGR_G_GetGeometryType( geom ) );
301 
302  int count = OGR_G_GetPointCount( geom );
303  QVector< double > x( count );
304  QVector< double > y( count );
305  QVector< double > z;
306  double *pz = nullptr;
307  if ( QgsWkbTypes::hasZ( wkbType ) )
308  {
309  z.resize( count );
310  pz = z.data();
311  }
312  double *pm = nullptr;
313  QVector< double > m;
314  if ( QgsWkbTypes::hasM( wkbType ) )
315  {
316  m.resize( count );
317  pm = m.data();
318  }
319  OGR_G_GetPointsZM( geom, x.data(), sizeof( double ), y.data(), sizeof( double ), pz, sizeof( double ), pm, sizeof( double ) );
320 
321  return qgis::make_unique< QgsLineString>( x, y, z, m, wkbType == QgsWkbTypes::LineString25D );
322 }
323 
325 {
326  switch ( ogrGeomType )
327  {
328  case wkbUnknown: return QgsWkbTypes::Type::Unknown;
329  case wkbPoint: return QgsWkbTypes::Type::Point;
330  case wkbLineString: return QgsWkbTypes::Type::LineString;
331  case wkbPolygon: return QgsWkbTypes::Type::Polygon;
332  case wkbMultiPoint: return QgsWkbTypes::Type::MultiPoint;
333  case wkbMultiLineString: return QgsWkbTypes::Type::MultiLineString;
334  case wkbMultiPolygon: return QgsWkbTypes::Type::MultiPolygon;
335  case wkbGeometryCollection: return QgsWkbTypes::Type::GeometryCollection;
336  case wkbCircularString: return QgsWkbTypes::Type::CircularString;
337  case wkbCompoundCurve: return QgsWkbTypes::Type::CompoundCurve;
338  case wkbCurvePolygon: return QgsWkbTypes::Type::CurvePolygon;
339  case wkbMultiCurve: return QgsWkbTypes::Type::MultiCurve;
340  case wkbMultiSurface: return QgsWkbTypes::Type::MultiSurface;
341  case wkbCurve: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
342  case wkbSurface: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
343  case wkbPolyhedralSurface: return QgsWkbTypes::Type::Unknown; // no actual matching
344  case wkbTIN: return QgsWkbTypes::Type::Unknown; // no actual matching
345  case wkbTriangle: return QgsWkbTypes::Type::Triangle;
346 
347  case wkbNone: return QgsWkbTypes::Type::NoGeometry;
348  case wkbLinearRing: return QgsWkbTypes::Type::LineString; // approximate match
349 
350  case wkbCircularStringZ: return QgsWkbTypes::Type::CircularStringZ;
351  case wkbCompoundCurveZ: return QgsWkbTypes::Type::CompoundCurveZ;
352  case wkbCurvePolygonZ: return QgsWkbTypes::Type::CurvePolygonZ;
353  case wkbMultiCurveZ: return QgsWkbTypes::Type::MultiCurveZ;
354  case wkbMultiSurfaceZ: return QgsWkbTypes::Type::MultiSurfaceZ;
355  case wkbCurveZ: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
356  case wkbSurfaceZ: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
357  case wkbPolyhedralSurfaceZ: return QgsWkbTypes::Type::Unknown; // no actual matching
358  case wkbTINZ: return QgsWkbTypes::Type::Unknown; // no actual matching
359  case wkbTriangleZ: return QgsWkbTypes::Type::TriangleZ;
360 
361  case wkbPointM: return QgsWkbTypes::Type::PointM;
362  case wkbLineStringM: return QgsWkbTypes::Type::LineStringM;
363  case wkbPolygonM: return QgsWkbTypes::Type::PolygonM;
364  case wkbMultiPointM: return QgsWkbTypes::Type::MultiPointM;
365  case wkbMultiLineStringM: return QgsWkbTypes::Type::MultiLineStringM;
366  case wkbMultiPolygonM: return QgsWkbTypes::Type::MultiPolygonM;
367  case wkbGeometryCollectionM: return QgsWkbTypes::Type::GeometryCollectionM;
368  case wkbCircularStringM: return QgsWkbTypes::Type::CircularStringM;
369  case wkbCompoundCurveM: return QgsWkbTypes::Type::CompoundCurveM;
370  case wkbCurvePolygonM: return QgsWkbTypes::Type::CurvePolygonM;
371  case wkbMultiCurveM: return QgsWkbTypes::Type::MultiCurveM;
372  case wkbMultiSurfaceM: return QgsWkbTypes::Type::MultiSurfaceM;
373  case wkbCurveM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
374  case wkbSurfaceM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
375  case wkbPolyhedralSurfaceM: return QgsWkbTypes::Type::Unknown; // no actual matching
376  case wkbTINM: return QgsWkbTypes::Type::Unknown; // no actual matching
377  case wkbTriangleM: return QgsWkbTypes::Type::TriangleM;
378 
379  case wkbPointZM: return QgsWkbTypes::Type::PointZM;
380  case wkbLineStringZM: return QgsWkbTypes::Type::LineStringZM;
381  case wkbPolygonZM: return QgsWkbTypes::Type::PolygonZM;
382  case wkbMultiPointZM: return QgsWkbTypes::Type::MultiPointZM;
383  case wkbMultiLineStringZM: return QgsWkbTypes::Type::MultiLineStringZM;
384  case wkbMultiPolygonZM: return QgsWkbTypes::Type::MultiPolygonZM;
385  case wkbGeometryCollectionZM: return QgsWkbTypes::Type::GeometryCollectionZM;
386  case wkbCircularStringZM: return QgsWkbTypes::Type::CircularStringZM;
387  case wkbCompoundCurveZM: return QgsWkbTypes::Type::CompoundCurveZM;
388  case wkbCurvePolygonZM: return QgsWkbTypes::Type::CurvePolygonZM;
389  case wkbMultiCurveZM: return QgsWkbTypes::Type::MultiCurveZM;
390  case wkbMultiSurfaceZM: return QgsWkbTypes::Type::MultiSurfaceZM;
391  case wkbCurveZM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
392  case wkbSurfaceZM: return QgsWkbTypes::Type::Unknown; // not an actual concrete type
393  case wkbPolyhedralSurfaceZM: return QgsWkbTypes::Type::Unknown; // no actual matching
394  case wkbTINZM: return QgsWkbTypes::Type::Unknown; // no actual matching
395  case wkbTriangleZM: return QgsWkbTypes::Type::TriangleZM;
396 
397  case wkbPoint25D: return QgsWkbTypes::Type::PointZ;
398  case wkbLineString25D: return QgsWkbTypes::Type::LineStringZ;
399  case wkbPolygon25D: return QgsWkbTypes::Type::PolygonZ;
400  case wkbMultiPoint25D: return QgsWkbTypes::Type::MultiPointZ;
401  case wkbMultiLineString25D: return QgsWkbTypes::Type::MultiLineStringZ;
402  case wkbMultiPolygon25D: return QgsWkbTypes::Type::MultiPolygonZ;
403  case wkbGeometryCollection25D: return QgsWkbTypes::Type::GeometryCollectionZ;
404  }
405 
406  // should not reach that point normally
407  return QgsWkbTypes::Type::Unknown;
408 }
409 
411 {
412  if ( !geom )
413  return QgsGeometry();
414 
415  const auto ogrGeomType = OGR_G_GetGeometryType( geom );
416  QgsWkbTypes::Type wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
417 
418  // optimised case for some geometry classes, avoiding wkb conversion on OGR/QGIS sides
419  // TODO - extend to other classes!
420  switch ( QgsWkbTypes::flatType( wkbType ) )
421  {
422  case QgsWkbTypes::Point:
423  {
424  return QgsGeometry( ogrGeometryToQgsPoint( geom ) );
425  }
426 
428  {
429  return QgsGeometry( ogrGeometryToQgsMultiPoint( geom ) );
430  }
431 
433  {
434  // optimised case for line -- avoid wkb conversion
435  return QgsGeometry( ogrGeometryToQgsLineString( geom ) );
436  }
437 
438  default:
439  break;
440  };
441 
442  // Fallback to inefficient WKB conversions
443 
444  if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
445  {
446  // Shapefile MultiPatch can be reported as GeometryCollectionZ of TINZ
447  if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
448  wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
449  {
450  auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
451  auto ret = ogrGeometryToQgsGeometry( newGeom );
452  OGR_G_DestroyGeometry( newGeom );
453  return ret;
454  }
455  }
456 
457  // get the wkb representation
458  int memorySize = OGR_G_WkbSize( geom );
459  unsigned char *wkb = new unsigned char[memorySize];
460  OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb );
461 
462  // Read original geometry type
463  uint32_t origGeomType;
464  memcpy( &origGeomType, wkb + 1, sizeof( uint32_t ) );
465  bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
466  bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
467 
468  // PolyhedralSurface and TINs are not supported, map them to multipolygons...
469  if ( origGeomType % 1000 == 16 ) // is TIN, TINZ, TINM or TINZM
470  {
471  // TIN has the same wkb layout as a multipolygon, just need to overwrite the geom types...
472  int nDims = 2 + hasZ + hasM;
473  uint32_t newMultiType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
474  uint32_t newSingleType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::Polygon, hasZ, hasM ) );
475  unsigned char *wkbptr = wkb;
476 
477  // Endianness
478  wkbptr += 1;
479 
480  // Overwrite geom type
481  memcpy( wkbptr, &newMultiType, sizeof( uint32_t ) );
482  wkbptr += 4;
483 
484  // Geom count
485  uint32_t numGeoms;
486  memcpy( &numGeoms, wkb + 5, sizeof( uint32_t ) );
487  wkbptr += 4;
488 
489  // For each part, overwrite the geometry type to polygon (Z|M)
490  for ( uint32_t i = 0; i < numGeoms; ++i )
491  {
492  // Endianness
493  wkbptr += 1;
494 
495  // Overwrite geom type
496  memcpy( wkbptr, &newSingleType, sizeof( uint32_t ) );
497  wkbptr += sizeof( uint32_t );
498 
499  // skip coordinates
500  uint32_t nRings;
501  memcpy( &nRings, wkbptr, sizeof( uint32_t ) );
502  wkbptr += sizeof( uint32_t );
503 
504  for ( uint32_t j = 0; j < nRings; ++j )
505  {
506  uint32_t nPoints;
507  memcpy( &nPoints, wkbptr, sizeof( uint32_t ) );
508  wkbptr += sizeof( uint32_t ) + sizeof( double ) * nDims * nPoints;
509  }
510  }
511  }
512  else if ( origGeomType % 1000 == 15 ) // PolyhedralSurface, PolyhedralSurfaceZ, PolyhedralSurfaceM or PolyhedralSurfaceZM
513  {
514  // PolyhedralSurface has the same wkb layout as a MultiPolygon, just need to overwrite the geom type...
515  uint32_t newType = static_cast<uint32_t>( QgsWkbTypes::zmType( QgsWkbTypes::MultiPolygon, hasZ, hasM ) );
516  // Overwrite geom type
517  memcpy( wkb + 1, &newType, sizeof( uint32_t ) );
518  }
519 
520  QgsGeometry g;
521  g.fromWkb( wkb, memorySize );
522  return g;
523 }
524 
525 QgsFeatureList QgsOgrUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
526 {
527  QgsFeatureList features;
528  if ( string.isEmpty() )
529  return features;
530 
531  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
532 
533  // create memory file system object from string buffer
534  QByteArray ba = string.toUtf8();
535  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
536  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
537 
538  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
539  if ( !hDS )
540  {
541  VSIUnlink( randomFileName.toUtf8().constData() );
542  return features;
543  }
544 
545  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
546  if ( !ogrLayer )
547  {
548  hDS.reset();
549  VSIUnlink( randomFileName.toUtf8().constData() );
550  return features;
551  }
552 
554  while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
555  {
556  QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
557  if ( feat.isValid() )
558  features << feat;
559  }
560 
561  hDS.reset();
562  VSIUnlink( randomFileName.toUtf8().constData() );
563 
564  return features;
565 }
566 
567 QgsFields QgsOgrUtils::stringToFields( const QString &string, QTextCodec *encoding )
568 {
569  QgsFields fields;
570  if ( string.isEmpty() )
571  return fields;
572 
573  QString randomFileName = QStringLiteral( "/vsimem/%1" ).arg( QUuid::createUuid().toString() );
574 
575  // create memory file system object from buffer
576  QByteArray ba = string.toUtf8();
577  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), reinterpret_cast< GByte * >( ba.data() ),
578  static_cast< vsi_l_offset >( ba.size() ), FALSE ) );
579 
580  gdal::ogr_datasource_unique_ptr hDS( OGROpen( randomFileName.toUtf8().constData(), false, nullptr ) );
581  if ( !hDS )
582  {
583  VSIUnlink( randomFileName.toUtf8().constData() );
584  return fields;
585  }
586 
587  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
588  if ( !ogrLayer )
589  {
590  hDS.reset();
591  VSIUnlink( randomFileName.toUtf8().constData() );
592  return fields;
593  }
594 
596  //read in the first feature only
597  if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
598  {
599  fields = readOgrFields( oFeat.get(), encoding );
600  }
601 
602  hDS.reset();
603  VSIUnlink( randomFileName.toUtf8().constData() );
604  return fields;
605 }
606 
607 QStringList QgsOgrUtils::cStringListToQStringList( char **stringList )
608 {
609  QStringList strings;
610 
611  // presume null terminated string list
612  for ( qgssize i = 0; stringList[i]; ++i )
613  {
614  strings.append( QString::fromUtf8( stringList[i] ) );
615  }
616 
617  return strings;
618 }
619 
void CORE_EXPORT operator()(OGRFeatureH feature)
Destroys an OGR feature, using the correct gdal calls.
Definition: qgsogrutils.cpp:52
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:162
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:211
void CORE_EXPORT operator()(OGRDataSourceH source)
Destroys an OGR data source, using the correct gdal calls.
Definition: qgsogrutils.cpp:36
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
#define OGR_F_IsFieldSetAndNotNull
Definition: qgsogrutils.cpp:31
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
static endian_t endian()
Returns whether this machine uses big or little endian.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:906
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
void CORE_EXPORT fast_delete_and_close(dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path)
Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying data store...
Definition: qgsogrutils.cpp:62
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
Definition: qgsogrutils.h:129
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
void CORE_EXPORT operator()(GDALDatasetH datasource)
Destroys an gdal dataset, using the correct gdal calls.
Definition: qgsogrutils.cpp:57
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:202
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
Definition: qgsogrutils.cpp:87
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:112
void * GDALDatasetH
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition: qgis.h:586
void CORE_EXPORT operator()(GDALWarpOptions *options)
Destroys GDAL warp options, using the correct gdal calls.
Definition: qgsogrutils.cpp:82
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:188
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
void CORE_EXPORT operator()(OGRGeometryH geometry)
Destroys an OGR geometry, using the correct gdal calls.
Definition: qgsogrutils.cpp:42
void CORE_EXPORT operator()(OGRFieldDefnH definition)
Destroys an OGR field definition, using the correct gdal calls.
Definition: qgsogrutils.cpp:47
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
static Type zmType(Type type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
Definition: qgswkbtypes.h:664
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:956
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Definition: qgsogrutils.h:114
static QStringList cStringListToQStringList(char **stringList)
Converts a c string list to a QStringList.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:565
QVariant::Type type
Definition: qgsfield.h:55