1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: OGR C API "Spy"
5 * Author: Even Rouault, even.rouault at spatialys.com
6 *
7 ******************************************************************************
8 * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "cpl_port.h"
30 #include "cpl_multiproc.h"
31 #include "ograpispy.h"
32
33 #include <cstdio>
34 #include <map>
35 #include <set>
36
37 #include "cpl_string.h"
38 #include "gdal.h"
39 #include "ogr_geometry.h"
40 #include "ogr_feature.h"
41 #include "ogr_spatialref.h"
42 #include "ogrsf_frmts.h"
43
44 CPL_CVSID("$Id: ograpispy.cpp 428c6a6a0a81364b703d448b3baa74bb17ae2cbd 2020-10-21 15:43:49 +0200 Even Rouault $")
45
46 #ifdef OGRAPISPY_ENABLED
47
48 int bOGRAPISpyEnabled = FALSE;
49 static CPLMutex* hMutex = nullptr;
50 static CPLString osSnapshotPath;
51 static CPLString osSpyFile;
52 static FILE* fpSpyFile = nullptr;
53 extern "C" int CPL_DLL GDALIsInGlobalDestructor(void);
54
55 // Keep in sync with cpl_conv.cpp
56 void OGRAPISPYCPLSetConfigOption(const char*, const char*);
57 void OGRAPISPYCPLSetThreadLocalConfigOption(const char*, const char*);
58
59 namespace
60 {
61
62 class LayerDescription
63 {
64 public:
65 int iLayer = -1;
66
67 LayerDescription() = default;
LayerDescription(int iLayerIn)68 explicit LayerDescription( int iLayerIn ): iLayer(iLayerIn) {}
69 };
70
71 class DatasetDescription
72 {
73 public:
74 int iDS = -1;
75 std::map<OGRLayerH, LayerDescription> oMapLayer{};
76
77 DatasetDescription() = default;
DatasetDescription(int iDSIn)78 explicit DatasetDescription( int iDSIn ) : iDS(iDSIn) {}
79 DatasetDescription& operator=(DatasetDescription&&) = default;
80 ~DatasetDescription();
81 };
82
83 class FeatureDefnDescription
84 {
85 public:
86 OGRFeatureDefnH hFDefn = nullptr;
87 int iUniqueNumber = -1;
88 std::map<OGRFieldDefnH, int> oMapFieldDefn{};
89 std::map<OGRGeomFieldDefnH, int> oMapGeomFieldDefn{};
90
91 FeatureDefnDescription() = default;
FeatureDefnDescription(OGRFeatureDefnH hFDefnIn,int iUniqueNumberIn)92 FeatureDefnDescription( OGRFeatureDefnH hFDefnIn, int iUniqueNumberIn ):
93 hFDefn(hFDefnIn), iUniqueNumber(iUniqueNumberIn) {}
94
95 FeatureDefnDescription(const FeatureDefnDescription&) = default;
96 FeatureDefnDescription& operator=(const FeatureDefnDescription&) = default;
97
98 void Free();
99 };
100
101 } // namespace
102
103 static std::map<GDALDatasetH, DatasetDescription> oMapDS;
104 static std::set<int> oSetDSIndex;
105 static std::map<OGRLayerH, CPLString> oGlobalMapLayer;
106 static OGRLayerH hLayerGetNextFeature = nullptr;
107 static OGRLayerH hLayerGetLayerDefn = nullptr;
108 static bool bDeferGetFieldCount = false;
109 static int nGetNextFeatureCalls = 0;
110 static std::set<CPLString> aoSetCreatedDS;
111 static std::map<OGRFeatureDefnH, FeatureDefnDescription> oMapFDefn;
112 static std::map<OGRGeomFieldDefnH, CPLString> oGlobalMapGeomFieldDefn;
113 static std::map<OGRFieldDefnH, CPLString> oGlobalMapFieldDefn;
114
Free()115 void FeatureDefnDescription::Free()
116 {
117 {
118 std::map<OGRGeomFieldDefnH, int>::iterator oIter =
119 oMapGeomFieldDefn.begin();
120 for( ; oIter != oMapGeomFieldDefn.end(); ++oIter )
121 oGlobalMapGeomFieldDefn.erase(oIter->first);
122 }
123 {
124 std::map<OGRFieldDefnH, int>::iterator oIter =
125 oMapFieldDefn.begin();
126 for( ; oIter != oMapFieldDefn.end(); ++oIter )
127 oGlobalMapFieldDefn.erase(oIter->first);
128 }
129 }
130
~DatasetDescription()131 DatasetDescription::~DatasetDescription()
132 {
133 if( !GDALIsInGlobalDestructor() )
134 {
135 std::map<OGRLayerH, LayerDescription>::iterator oIter =
136 oMapLayer.begin();
137 for( ; oIter != oMapLayer.end(); ++oIter )
138 oGlobalMapLayer.erase(oIter->first);
139 }
140 }
141
OGRAPISpyDestroyMutex()142 void OGRAPISpyDestroyMutex()
143 {
144 if( hMutex )
145 {
146 CPLDestroyMutex(hMutex);
147 hMutex = nullptr;
148
149 aoSetCreatedDS.clear();
150 oMapFDefn.clear();
151 oGlobalMapGeomFieldDefn.clear();
152 oGlobalMapFieldDefn.clear();
153 }
154 }
155
OGRAPISpyFileReopen()156 static void OGRAPISpyFileReopen()
157 {
158 if( fpSpyFile == nullptr )
159 {
160 fpSpyFile = fopen(osSpyFile, "ab");
161 if( fpSpyFile == nullptr )
162 fpSpyFile = stderr;
163 }
164 }
165
OGRAPISpyFileClose()166 static void OGRAPISpyFileClose()
167 {
168 if( fpSpyFile != stdout && fpSpyFile != stderr )
169 {
170 fclose(fpSpyFile);
171 fpSpyFile = nullptr;
172 }
173 }
174
OGRAPISpyEnabled()175 static bool OGRAPISpyEnabled()
176 {
177 if( bOGRAPISpyEnabled < 0 )
178 return false;
179
180 const char* pszSpyFile = CPLGetConfigOption("OGR_API_SPY_FILE", nullptr);
181 bOGRAPISpyEnabled = pszSpyFile != nullptr;
182 if( !bOGRAPISpyEnabled )
183 {
184 osSpyFile.resize(0);
185 aoSetCreatedDS.clear();
186 return false;
187 }
188 if( !osSpyFile.empty() )
189 return true;
190
191 CPLMutexHolderD(&hMutex);
192 if( !osSpyFile.empty() )
193 return true;
194
195 osSpyFile = pszSpyFile;
196
197 const char* pszSnapshotPath =
198 CPLGetConfigOption("OGR_API_SPY_SNAPSHOT_PATH", ".");
199 if( EQUAL(pszSnapshotPath, "NO") )
200 osSnapshotPath = "";
201 else
202 osSnapshotPath = pszSnapshotPath;
203
204 if( EQUAL(pszSpyFile, "stdout") )
205 fpSpyFile = stdout;
206 else if( EQUAL(pszSpyFile, "stderr") )
207 fpSpyFile = stderr;
208 else
209 fpSpyFile = fopen(pszSpyFile, "wb");
210 if( fpSpyFile == nullptr )
211 fpSpyFile = stderr;
212
213 fprintf(fpSpyFile,
214 "# This file is generated by the OGR_API_SPY mechanism.\n");
215 fprintf(fpSpyFile, "import os\n");
216 fprintf(fpSpyFile, "import shutil\n");
217 fprintf(fpSpyFile, "from osgeo import gdal\n");
218 fprintf(fpSpyFile, "from osgeo import ogr\n");
219 fprintf(fpSpyFile, "from osgeo import osr\n");
220 // To make pyflakes happy in case it is unused later.
221 fprintf(fpSpyFile, "os.access\n");
222 fprintf(fpSpyFile, "shutil.copy\n"); // Same here.
223 fprintf(fpSpyFile, "\n");
224
225 return true;
226 }
227
OGRAPISpyGetOptions(char ** papszOptions)228 static CPLString OGRAPISpyGetOptions( char** papszOptions )
229 {
230 if( papszOptions == nullptr )
231 {
232 return "[]";
233 }
234
235 CPLString options = "[";
236 for( char** papszIter = papszOptions; *papszIter != nullptr; papszIter++ )
237 {
238 if( papszIter != papszOptions )
239 options += ", ";
240 options += "'";
241 options += *papszIter;
242 options += "'";
243 }
244 options += "]";
245
246 return options;
247 }
248
OGRAPISpyGetString(const char * pszStr)249 static CPLString OGRAPISpyGetString( const char* pszStr )
250 {
251 if( pszStr == nullptr )
252 return "None";
253 CPLString osRet = "'";
254 while( *pszStr )
255 {
256 if( *pszStr == '\'' )
257 osRet += "\\'";
258 else if( *pszStr == '\\' )
259 osRet += "\\\\";
260 else
261 osRet += *pszStr;
262 pszStr++;
263 }
264 osRet += "'";
265 return osRet;
266 }
267
OGRAPISpyGetDSVar(GDALDatasetH hDS)268 static CPLString OGRAPISpyGetDSVar( GDALDatasetH hDS )
269 {
270 if( hDS && oMapDS.find(hDS) == oMapDS.end() )
271 {
272 int i = 1;
273 while( oSetDSIndex.find(i) != oSetDSIndex.end() )
274 i ++;
275 oMapDS[hDS] = DatasetDescription(i);
276 oSetDSIndex.insert(i);
277 }
278 return CPLSPrintf("ds%d", hDS ? oMapDS[hDS].iDS : 0);
279 }
280
OGRAPISpyGetLayerVar(OGRLayerH hLayer)281 static CPLString OGRAPISpyGetLayerVar( OGRLayerH hLayer )
282 {
283 return oGlobalMapLayer[hLayer];
284 }
285
OGRAPISpyGetAndRegisterLayerVar(GDALDatasetH hDS,OGRLayerH hLayer)286 static CPLString OGRAPISpyGetAndRegisterLayerVar( GDALDatasetH hDS,
287 OGRLayerH hLayer )
288 {
289 DatasetDescription& dd = oMapDS[hDS];
290 if( hLayer && dd.oMapLayer.find(hLayer) == dd.oMapLayer.end() )
291 {
292 const int i = static_cast<int>(dd.oMapLayer.size()) + 1;
293 dd.oMapLayer[hLayer] = LayerDescription(i);
294 oGlobalMapLayer[hLayer] =
295 OGRAPISpyGetDSVar(hDS) + "_" + CPLSPrintf("lyr%d", i);
296 }
297
298 return OGRAPISpyGetDSVar(hDS) + "_" +
299 CPLSPrintf("lyr%d", hLayer ? dd.oMapLayer[hLayer].iLayer : 0);
300 }
301
OGRAPISpyGetSRS(OGRSpatialReferenceH hSpatialRef)302 static CPLString OGRAPISpyGetSRS( OGRSpatialReferenceH hSpatialRef )
303 {
304 if( hSpatialRef == nullptr )
305 return "None";
306
307 char* pszWKT = nullptr;
308 OGRSpatialReference::FromHandle(hSpatialRef)->exportToWkt(&pszWKT);
309 const char* pszRet =
310 CPLSPrintf(R"(osr.SpatialReference("""%s"""))", pszWKT);
311 CPLFree(pszWKT);
312 return pszRet;
313 }
314
OGRAPISpyGetGeom(OGRGeometryH hGeom)315 static CPLString OGRAPISpyGetGeom( OGRGeometryH hGeom )
316 {
317 if( hGeom == nullptr )
318 return "None";
319
320 char* pszWKT = nullptr;
321 OGRGeometry::FromHandle(hGeom)->exportToWkt(&pszWKT);
322 const char* pszRet = CPLSPrintf("ogr.CreateGeometryFromWkt('%s')", pszWKT);
323 CPLFree(pszWKT);
324 return pszRet;
325 }
326
327 #define casePrefixOgrDot(x) case x: return "ogr." #x;
328
OGRAPISpyGetGeomType(OGRwkbGeometryType eType)329 static CPLString OGRAPISpyGetGeomType( OGRwkbGeometryType eType )
330 {
331 switch( eType )
332 {
333 casePrefixOgrDot(wkbUnknown)
334 casePrefixOgrDot(wkbPoint)
335 casePrefixOgrDot(wkbLineString)
336 casePrefixOgrDot(wkbPolygon)
337 casePrefixOgrDot(wkbMultiPoint)
338 casePrefixOgrDot(wkbMultiLineString)
339 casePrefixOgrDot(wkbMultiPolygon)
340 casePrefixOgrDot(wkbGeometryCollection)
341 casePrefixOgrDot(wkbCircularString)
342 casePrefixOgrDot(wkbCompoundCurve)
343 casePrefixOgrDot(wkbCurvePolygon)
344 casePrefixOgrDot(wkbMultiCurve)
345 casePrefixOgrDot(wkbMultiSurface)
346 casePrefixOgrDot(wkbCurve)
347 casePrefixOgrDot(wkbSurface)
348 casePrefixOgrDot(wkbNone)
349 casePrefixOgrDot(wkbLinearRing)
350 casePrefixOgrDot(wkbCircularStringZ)
351 casePrefixOgrDot(wkbCompoundCurveZ)
352 casePrefixOgrDot(wkbCurvePolygonZ)
353 casePrefixOgrDot(wkbMultiCurveZ)
354 casePrefixOgrDot(wkbMultiSurfaceZ)
355 casePrefixOgrDot(wkbCurveZ)
356 casePrefixOgrDot(wkbSurfaceZ)
357 casePrefixOgrDot(wkbPoint25D)
358 casePrefixOgrDot(wkbLineString25D)
359 casePrefixOgrDot(wkbPolygon25D)
360 casePrefixOgrDot(wkbMultiPoint25D)
361 casePrefixOgrDot(wkbMultiLineString25D)
362 casePrefixOgrDot(wkbMultiPolygon25D)
363 casePrefixOgrDot(wkbGeometryCollection25D)
364 casePrefixOgrDot(wkbPolyhedralSurface)
365 casePrefixOgrDot(wkbTIN)
366 casePrefixOgrDot(wkbTriangle)
367 casePrefixOgrDot(wkbPolyhedralSurfaceZ)
368 casePrefixOgrDot(wkbTINZ)
369 casePrefixOgrDot(wkbTriangleZ)
370 casePrefixOgrDot(wkbPointM)
371 casePrefixOgrDot(wkbLineStringM)
372 casePrefixOgrDot(wkbPolygonM)
373 casePrefixOgrDot(wkbMultiPointM)
374 casePrefixOgrDot(wkbMultiLineStringM)
375 casePrefixOgrDot(wkbMultiPolygonM)
376 casePrefixOgrDot(wkbGeometryCollectionM)
377 casePrefixOgrDot(wkbCircularStringM)
378 casePrefixOgrDot(wkbCompoundCurveM)
379 casePrefixOgrDot(wkbCurvePolygonM)
380 casePrefixOgrDot(wkbMultiCurveM)
381 casePrefixOgrDot(wkbMultiSurfaceM)
382 casePrefixOgrDot(wkbCurveM)
383 casePrefixOgrDot(wkbSurfaceM)
384 casePrefixOgrDot(wkbPolyhedralSurfaceM)
385 casePrefixOgrDot(wkbTINM)
386 casePrefixOgrDot(wkbTriangleM)
387 casePrefixOgrDot(wkbPointZM)
388 casePrefixOgrDot(wkbLineStringZM)
389 casePrefixOgrDot(wkbPolygonZM)
390 casePrefixOgrDot(wkbMultiPointZM)
391 casePrefixOgrDot(wkbMultiLineStringZM)
392 casePrefixOgrDot(wkbMultiPolygonZM)
393 casePrefixOgrDot(wkbGeometryCollectionZM)
394 casePrefixOgrDot(wkbCircularStringZM)
395 casePrefixOgrDot(wkbCompoundCurveZM)
396 casePrefixOgrDot(wkbCurvePolygonZM)
397 casePrefixOgrDot(wkbMultiCurveZM)
398 casePrefixOgrDot(wkbMultiSurfaceZM)
399 casePrefixOgrDot(wkbCurveZM)
400 casePrefixOgrDot(wkbSurfaceZM)
401 casePrefixOgrDot(wkbPolyhedralSurfaceZM)
402 casePrefixOgrDot(wkbTriangleZM)
403 casePrefixOgrDot(wkbTINZM)
404
405 }
406 return "error";
407 }
408
OGRAPISpyGetFieldType(OGRFieldType eType)409 static CPLString OGRAPISpyGetFieldType(OGRFieldType eType)
410 {
411 switch( eType )
412 {
413 casePrefixOgrDot(OFTInteger)
414 casePrefixOgrDot(OFTInteger64)
415 casePrefixOgrDot(OFTIntegerList)
416 casePrefixOgrDot(OFTInteger64List)
417 casePrefixOgrDot(OFTReal)
418 casePrefixOgrDot(OFTRealList)
419 casePrefixOgrDot(OFTString)
420 casePrefixOgrDot(OFTStringList)
421 casePrefixOgrDot(OFTWideString)
422 casePrefixOgrDot(OFTWideStringList)
423 casePrefixOgrDot(OFTBinary)
424 casePrefixOgrDot(OFTDate)
425 casePrefixOgrDot(OFTTime)
426 casePrefixOgrDot(OFTDateTime)
427 }
428 return "error";
429 }
430
431 #undef casePrefixOgrDot
432
OGRAPISpyGetFeatureDefnVar(OGRFeatureDefnH hFDefn)433 static CPLString OGRAPISpyGetFeatureDefnVar( OGRFeatureDefnH hFDefn )
434 {
435 std::map<OGRFeatureDefnH, FeatureDefnDescription>::iterator oIter =
436 oMapFDefn.find(hFDefn);
437 int i = 0;
438 if( oIter == oMapFDefn.end() )
439 {
440 i = static_cast<int>(oMapFDefn.size()) + 1;
441 oMapFDefn[hFDefn] = FeatureDefnDescription(hFDefn, i);
442
443 // So that we can check when they are no longer used.
444 OGRFeatureDefn::FromHandle(hFDefn)->Reference();
445 }
446 else
447 {
448 i = oIter->second.iUniqueNumber;
449 }
450 return CPLSPrintf("fdefn%d", i);
451 }
452
OGRAPISpyFlushDefered()453 static void OGRAPISpyFlushDefered()
454 {
455 OGRAPISpyFileReopen();
456 if( hLayerGetLayerDefn != nullptr )
457 {
458 OGRFeatureDefnH hDefn =
459 OGRFeatureDefn::ToHandle(
460 OGRLayer::FromHandle(hLayerGetLayerDefn)->
461 GetLayerDefn());
462 fprintf(fpSpyFile, "%s = %s.GetLayerDefn()\n",
463 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
464 OGRAPISpyGetLayerVar(hLayerGetLayerDefn).c_str());
465
466 if( bDeferGetFieldCount )
467 {
468 fprintf(fpSpyFile, "%s.GetFieldCount()\n",
469 OGRAPISpyGetFeatureDefnVar(hDefn).c_str());
470 bDeferGetFieldCount = false;
471 }
472
473 hLayerGetLayerDefn = nullptr;
474 }
475
476 if( nGetNextFeatureCalls == 1)
477 {
478 fprintf(fpSpyFile, "%s.GetNextFeature()\n",
479 OGRAPISpyGetLayerVar(hLayerGetNextFeature).c_str());
480 hLayerGetNextFeature = nullptr;
481 nGetNextFeatureCalls = 0;
482 }
483 else if( nGetNextFeatureCalls > 0)
484 {
485 fprintf(fpSpyFile, "for i in range(%d):\n", nGetNextFeatureCalls);
486 fprintf(fpSpyFile, " %s.GetNextFeature()\n",
487 OGRAPISpyGetLayerVar(hLayerGetNextFeature).c_str());
488 hLayerGetNextFeature = nullptr;
489 nGetNextFeatureCalls = 0;
490 }
491 }
492
OGRAPISpyOpenTakeSnapshot(const char * pszName,int bUpdate)493 int OGRAPISpyOpenTakeSnapshot( const char* pszName, int bUpdate )
494 {
495 if( !OGRAPISpyEnabled() || !bUpdate || osSnapshotPath.empty() ||
496 aoSetCreatedDS.find(pszName) != aoSetCreatedDS.end() )
497 return -1;
498 OGRAPISpyFlushDefered();
499
500 VSIStatBufL sStat;
501 if( VSIStatL( pszName, &sStat ) == 0 )
502 {
503 bOGRAPISpyEnabled = -1;
504 GDALDatasetH hDS =
505 GDALOpenEx(pszName, GDAL_OF_VECTOR, nullptr, nullptr, nullptr);
506 char** papszFileList = hDS ? GDALDataset::FromHandle(hDS)->GetFileList() : nullptr;
507 GDALClose(hDS);
508 bOGRAPISpyEnabled = true;
509 if( papszFileList )
510 {
511 int i = 1;
512 CPLString osBaseDir;
513 CPLString osSrcDir;
514 CPLString osWorkingDir;
515 while( true )
516 {
517 osBaseDir =
518 CPLFormFilename(osSnapshotPath,
519 CPLSPrintf("snapshot_%d", i), nullptr );
520 if( VSIStatL( osBaseDir, &sStat ) != 0 )
521 break;
522 i++;
523 }
524 VSIMkdir( osSnapshotPath, 0777 );
525 VSIMkdir( osBaseDir, 0777 );
526 osSrcDir = CPLFormFilename( osBaseDir, "source", nullptr );
527 VSIMkdir( osSrcDir, 0777 );
528 osWorkingDir = CPLFormFilename( osBaseDir, "working", nullptr );
529 VSIMkdir( osWorkingDir, 0777 );
530
531 OGRAPISpyFileReopen();
532 fprintf(fpSpyFile, "# Take snapshot of %s\n", pszName);
533 fprintf(fpSpyFile, "try:\n");
534 fprintf(fpSpyFile, " shutil.rmtree('%s')\n",
535 osWorkingDir.c_str());
536 fprintf(fpSpyFile, "except:\n");
537 fprintf(fpSpyFile, " pass\n");
538 fprintf(fpSpyFile, "os.mkdir('%s')\n", osWorkingDir.c_str());
539 for( char** papszIter = papszFileList; *papszIter; papszIter++ )
540 {
541 CPLString osSnapshotSrcFile = CPLFormFilename(
542 osSrcDir, CPLGetFilename(*papszIter), nullptr);
543 CPLString osSnapshotWorkingFile = CPLFormFilename(
544 osWorkingDir, CPLGetFilename(*papszIter), nullptr);
545 CPLCopyFile( osSnapshotSrcFile, *papszIter );
546 CPLCopyFile( osSnapshotWorkingFile, *papszIter );
547 fprintf(fpSpyFile, "shutil.copy('%s', '%s')\n",
548 osSnapshotSrcFile.c_str(),
549 osSnapshotWorkingFile.c_str());
550 }
551 CSLDestroy(papszFileList);
552 return i;
553 }
554 }
555 return -1;
556 }
557
OGRAPISpyOpen(const char * pszName,int bUpdate,int iSnapshot,GDALDatasetH * phDS)558 void OGRAPISpyOpen( const char* pszName, int bUpdate, int iSnapshot,
559 GDALDatasetH* phDS )
560 {
561 if( !OGRAPISpyEnabled() ) return;
562 CPLMutexHolderD(&hMutex);
563 OGRAPISpyFlushDefered();
564
565 CPLString osName;
566 if( iSnapshot > 0 )
567 {
568 CPLString osBaseDir =
569 CPLFormFilename(osSnapshotPath,
570 CPLSPrintf("snapshot_%d", iSnapshot), nullptr );
571 CPLString osWorkingDir = CPLFormFilename( osBaseDir, "working", nullptr );
572 osName = CPLFormFilename(osWorkingDir, CPLGetFilename(pszName), nullptr);
573 pszName = osName.c_str();
574
575 if( *phDS != nullptr )
576 {
577 bOGRAPISpyEnabled = -1;
578 GDALClose( GDALDataset::FromHandle(*phDS) );
579 *phDS = GDALOpenEx(pszName,
580 GDAL_OF_VECTOR | GDAL_OF_UPDATE,
581 nullptr, nullptr, nullptr);
582 bOGRAPISpyEnabled = true;
583 }
584 }
585
586 OGRAPISpyFileReopen();
587 if( *phDS != nullptr )
588 fprintf(fpSpyFile,
589 "%s = ",
590 OGRAPISpyGetDSVar(*phDS).c_str());
591 if( bUpdate )
592 fprintf(fpSpyFile, "gdal.OpenEx(%s, gdal.OF_VECTOR | gdal.OF_UPDATE)\n",
593 OGRAPISpyGetString(pszName).c_str());
594 else
595 fprintf(fpSpyFile, "gdal.OpenEx(%s, gdal.OF_VECTOR)\n",
596 OGRAPISpyGetString(pszName).c_str());
597 OGRAPISpyFileClose();
598 }
599
OGRAPISpyPreClose(GDALDatasetH hDS)600 void OGRAPISpyPreClose( GDALDatasetH hDS )
601 {
602 if( !OGRAPISpyEnabled() ) return;
603 CPLMutexHolderD(&hMutex);
604 OGRAPISpyFlushDefered();
605 fprintf(fpSpyFile, "ds%d = None\n", oMapDS[hDS].iDS);
606 oSetDSIndex.erase(oMapDS[hDS].iDS);
607 oMapDS.erase(hDS);
608 OGRAPISpyFileClose();
609 }
610
OGRAPISpyPostClose()611 void OGRAPISpyPostClose()
612 {
613 if( !GDALIsInGlobalDestructor() )
614 {
615 if( !OGRAPISpyEnabled() ) return;
616 CPLMutexHolderD(&hMutex);
617 std::map<OGRFeatureDefnH, FeatureDefnDescription>::iterator oIter =
618 oMapFDefn.begin();
619 std::vector<OGRFeatureDefnH> oArray;
620 for( ; oIter != oMapFDefn.end(); ++oIter )
621 {
622 FeatureDefnDescription& featureDefnDescription = oIter->second;
623 if( OGRFeatureDefn::FromHandle(featureDefnDescription.hFDefn)->
624 GetReferenceCount() == 1 )
625 {
626 oArray.push_back(featureDefnDescription.hFDefn);
627 }
628 }
629 for( auto& hFDefn: oArray )
630 {
631 FeatureDefnDescription& featureDefnDescription =
632 oMapFDefn[hFDefn];
633 OGRFeatureDefn::FromHandle(featureDefnDescription.hFDefn)->Release();
634 featureDefnDescription.Free();
635 oMapFDefn.erase(hFDefn);
636 }
637 }
638 }
639
OGRAPISpyCreateDataSource(OGRSFDriverH hDriver,const char * pszName,char ** papszOptions,OGRDataSourceH hDS)640 void OGRAPISpyCreateDataSource( OGRSFDriverH hDriver, const char* pszName,
641 char** papszOptions, OGRDataSourceH hDS )
642 {
643 if( !OGRAPISpyEnabled() ) return;
644 CPLMutexHolderD(&hMutex);
645 OGRAPISpyFlushDefered();
646 if( hDS != nullptr )
647 fprintf(fpSpyFile, "%s = ", OGRAPISpyGetDSVar(hDS).c_str());
648 fprintf(fpSpyFile,
649 "ogr.GetDriverByName('%s').CreateDataSource(%s, options=%s)\n",
650 GDALGetDriverShortName(reinterpret_cast<GDALDriverH>(hDriver)),
651 OGRAPISpyGetString(pszName).c_str(),
652 OGRAPISpyGetOptions(papszOptions).c_str());
653 if( hDS != nullptr )
654 {
655 aoSetCreatedDS.insert(pszName);
656 }
657 OGRAPISpyFileClose();
658 }
659
OGRAPISpyDeleteDataSource(OGRSFDriverH hDriver,const char * pszName)660 void OGRAPISpyDeleteDataSource( OGRSFDriverH hDriver, const char* pszName )
661 {
662 if( !OGRAPISpyEnabled() ) return;
663 CPLMutexHolderD(&hMutex);
664 OGRAPISpyFlushDefered();
665 fprintf(fpSpyFile, "ogr.GetDriverByName('%s').DeleteDataSource(%s)\n",
666 GDALGetDriverShortName(reinterpret_cast<GDALDriverH>(hDriver)),
667 OGRAPISpyGetString(pszName).c_str());
668 aoSetCreatedDS.erase(pszName);
669 OGRAPISpyFileClose();
670 }
671
OGRAPISpy_DS_GetLayer(GDALDatasetH hDS,int iLayer,OGRLayerH hLayer)672 void OGRAPISpy_DS_GetLayer( GDALDatasetH hDS, int iLayer, OGRLayerH hLayer )
673 {
674 CPLMutexHolderD(&hMutex);
675 OGRAPISpyFlushDefered();
676 if( hLayer != nullptr )
677 fprintf(fpSpyFile, "%s = ",
678 OGRAPISpyGetAndRegisterLayerVar(hDS, hLayer).c_str());
679 fprintf(fpSpyFile, "%s.GetLayer(%d)\n",
680 OGRAPISpyGetDSVar(hDS).c_str(),
681 iLayer);
682 OGRAPISpyFileClose();
683 }
684
OGRAPISpy_DS_GetLayerCount(GDALDatasetH hDS)685 void OGRAPISpy_DS_GetLayerCount( GDALDatasetH hDS )
686 {
687 CPLMutexHolderD(&hMutex);
688 OGRAPISpyFlushDefered();
689 fprintf(fpSpyFile, "%s.GetLayerCount()\n", OGRAPISpyGetDSVar(hDS).c_str());
690 OGRAPISpyFileClose();
691 }
692
OGRAPISpy_DS_GetLayerByName(GDALDatasetH hDS,const char * pszLayerName,OGRLayerH hLayer)693 void OGRAPISpy_DS_GetLayerByName( GDALDatasetH hDS, const char* pszLayerName,
694 OGRLayerH hLayer )
695 {
696 CPLMutexHolderD(&hMutex);
697 OGRAPISpyFlushDefered();
698 if( hLayer != nullptr )
699 fprintf(fpSpyFile, "%s = ",
700 OGRAPISpyGetAndRegisterLayerVar(hDS, hLayer).c_str());
701 fprintf(fpSpyFile, "%s.GetLayerByName(%s)\n",
702 OGRAPISpyGetDSVar(hDS).c_str(),
703 OGRAPISpyGetString(pszLayerName).c_str());
704 OGRAPISpyFileClose();
705 }
706
OGRAPISpy_DS_ExecuteSQL(GDALDatasetH hDS,const char * pszStatement,OGRGeometryH hSpatialFilter,const char * pszDialect,OGRLayerH hLayer)707 void OGRAPISpy_DS_ExecuteSQL( GDALDatasetH hDS,
708 const char *pszStatement,
709 OGRGeometryH hSpatialFilter,
710 const char *pszDialect,
711 OGRLayerH hLayer )
712 {
713 CPLMutexHolderD(&hMutex);
714 OGRAPISpyFlushDefered();
715 if( hLayer != nullptr )
716 fprintf(fpSpyFile, "%s = ",
717 OGRAPISpyGetAndRegisterLayerVar(hDS, hLayer).c_str());
718 fprintf(fpSpyFile, "%s.ExecuteSQL(%s, %s, %s)\n",
719 OGRAPISpyGetDSVar(hDS).c_str(),
720 OGRAPISpyGetString(pszStatement).c_str(),
721 OGRAPISpyGetGeom(hSpatialFilter).c_str(),
722 OGRAPISpyGetString(pszDialect).c_str());
723 OGRAPISpyFileClose();
724 }
725
OGRAPISpy_DS_ReleaseResultSet(GDALDatasetH hDS,OGRLayerH hLayer)726 void OGRAPISpy_DS_ReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
727 {
728 CPLMutexHolderD(&hMutex);
729 OGRAPISpyFlushDefered();
730 fprintf(fpSpyFile, "%s.ReleaseResultSet(%s)\n",
731 OGRAPISpyGetDSVar(hDS).c_str(),
732 (hLayer) ? OGRAPISpyGetLayerVar(hLayer).c_str() : "None");
733
734 DatasetDescription& dd = oMapDS[hDS];
735 dd.oMapLayer.erase(hLayer);
736 oGlobalMapLayer.erase(hLayer);
737
738 OGRAPISpyFileClose();
739 }
740
OGRAPISpy_DS_CreateLayer(GDALDatasetH hDS,const char * pszName,OGRSpatialReferenceH hSpatialRef,OGRwkbGeometryType eType,char ** papszOptions,OGRLayerH hLayer)741 void OGRAPISpy_DS_CreateLayer( GDALDatasetH hDS,
742 const char * pszName,
743 OGRSpatialReferenceH hSpatialRef,
744 OGRwkbGeometryType eType,
745 char ** papszOptions,
746 OGRLayerH hLayer )
747 {
748 CPLMutexHolderD(&hMutex);
749 OGRAPISpyFlushDefered();
750 if( hLayer != nullptr )
751 fprintf(fpSpyFile, "%s = ",
752 OGRAPISpyGetAndRegisterLayerVar(hDS, hLayer).c_str());
753 fprintf(fpSpyFile,
754 "%s.CreateLayer(%s, srs=%s, geom_type=%s, options=%s)\n",
755 OGRAPISpyGetDSVar(hDS).c_str(),
756 OGRAPISpyGetString(pszName).c_str(),
757 OGRAPISpyGetSRS(hSpatialRef).c_str(),
758 OGRAPISpyGetGeomType(eType).c_str(),
759 OGRAPISpyGetOptions(papszOptions).c_str());
760 OGRAPISpyFileClose();
761 }
762
OGRAPISpy_DS_DeleteLayer(GDALDatasetH hDS,int iLayer)763 void OGRAPISpy_DS_DeleteLayer( GDALDatasetH hDS, int iLayer )
764 {
765 CPLMutexHolderD(&hMutex);
766 OGRAPISpyFlushDefered();
767 fprintf(fpSpyFile, "%s.DeleteLayer(%d)\n",
768 OGRAPISpyGetDSVar(hDS).c_str(), iLayer);
769 // Should perhaps remove from the maps.
770 OGRAPISpyFileClose();
771 }
772
OGRAPISpy_Dataset_StartTransaction(GDALDatasetH hDS,int bForce)773 void OGRAPISpy_Dataset_StartTransaction( GDALDatasetH hDS, int bForce )
774 {
775 CPLMutexHolderD(&hMutex);
776 OGRAPISpyFlushDefered();
777 fprintf(fpSpyFile, "%s.StartTransaction(%d)\n",
778 OGRAPISpyGetDSVar(hDS).c_str(),
779 bForce);
780 OGRAPISpyFileClose();
781 }
782
OGRAPISpy_Dataset_CommitTransaction(GDALDatasetH hDS)783 void OGRAPISpy_Dataset_CommitTransaction( GDALDatasetH hDS )
784 {
785 CPLMutexHolderD(&hMutex);
786 OGRAPISpyFlushDefered();
787 fprintf(fpSpyFile, "%s.CommitTransaction()\n",
788 OGRAPISpyGetDSVar(hDS).c_str());
789 OGRAPISpyFileClose();
790 }
791
OGRAPISpy_Dataset_RollbackTransaction(GDALDatasetH hDS)792 void OGRAPISpy_Dataset_RollbackTransaction( GDALDatasetH hDS )
793 {
794 CPLMutexHolderD(&hMutex);
795 OGRAPISpyFlushDefered();
796 fprintf(fpSpyFile, "%s.RollbackTransaction()\n",
797 OGRAPISpyGetDSVar(hDS).c_str());
798 OGRAPISpyFileClose();
799 }
800
OGRAPISpy_L_GetFeatureCount(OGRLayerH hLayer,int bForce)801 void OGRAPISpy_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
802 {
803 CPLMutexHolderD(&hMutex);
804 OGRAPISpyFlushDefered();
805 fprintf(fpSpyFile, "%s.GetFeatureCount(force=%d)\n",
806 OGRAPISpyGetLayerVar(hLayer).c_str(), bForce);
807 OGRAPISpyFileClose();
808 }
809
OGRAPISpy_L_GetExtent(OGRLayerH hLayer,int bForce)810 void OGRAPISpy_L_GetExtent( OGRLayerH hLayer, int bForce )
811 {
812 CPLMutexHolderD(&hMutex);
813 OGRAPISpyFlushDefered();
814 fprintf(fpSpyFile, "%s.GetExtent(force=%d)\n",
815 OGRAPISpyGetLayerVar(hLayer).c_str(), bForce);
816 OGRAPISpyFileClose();
817 }
818
OGRAPISpy_L_GetExtentEx(OGRLayerH hLayer,int iGeomField,int bForce)819 void OGRAPISpy_L_GetExtentEx( OGRLayerH hLayer, int iGeomField, int bForce )
820 {
821 CPLMutexHolderD(&hMutex);
822 OGRAPISpyFlushDefered();
823 fprintf(fpSpyFile, "%s.GetExtent(geom_field=%d, force=%d)\n",
824 OGRAPISpyGetLayerVar(hLayer).c_str(), iGeomField, bForce);
825 OGRAPISpyFileClose();
826 }
827
OGRAPISpy_L_SetAttributeFilter(OGRLayerH hLayer,const char * pszFilter)828 void OGRAPISpy_L_SetAttributeFilter( OGRLayerH hLayer, const char* pszFilter )
829 {
830 CPLMutexHolderD(&hMutex);
831 OGRAPISpyFlushDefered();
832 fprintf(fpSpyFile, "%s.SetAttributeFilter(%s)\n",
833 OGRAPISpyGetLayerVar(hLayer).c_str(),
834 OGRAPISpyGetString(pszFilter).c_str());
835 OGRAPISpyFileClose();
836 }
837
OGRAPISpy_L_GetFeature(OGRLayerH hLayer,GIntBig nFeatureId)838 void OGRAPISpy_L_GetFeature( OGRLayerH hLayer, GIntBig nFeatureId )
839 {
840 CPLMutexHolderD(&hMutex);
841 OGRAPISpyFlushDefered();
842 fprintf(fpSpyFile, "%s.GetFeature(" CPL_FRMT_GIB ")\n",
843 OGRAPISpyGetLayerVar(hLayer).c_str(), nFeatureId);
844 OGRAPISpyFileClose();
845 }
846
OGRAPISpy_L_SetNextByIndex(OGRLayerH hLayer,GIntBig nIndex)847 void OGRAPISpy_L_SetNextByIndex( OGRLayerH hLayer, GIntBig nIndex )
848 {
849 CPLMutexHolderD(&hMutex);
850 OGRAPISpyFlushDefered();
851 fprintf(fpSpyFile, "%s.SetNextByIndex(" CPL_FRMT_GIB ")\n",
852 OGRAPISpyGetLayerVar(hLayer).c_str(), nIndex);
853 OGRAPISpyFileClose();
854 }
855
OGRAPISpy_L_GetNextFeature(OGRLayerH hLayer)856 void OGRAPISpy_L_GetNextFeature( OGRLayerH hLayer )
857 {
858 CPLMutexHolderD(&hMutex);
859 if( hLayerGetNextFeature != hLayer )
860 {
861 OGRAPISpyFlushDefered();
862 OGRAPISpyFileClose();
863 }
864 hLayerGetNextFeature = hLayer;
865 nGetNextFeatureCalls++;
866 }
867
OGRAPISpyDumpFeature(OGRFeatureH hFeat)868 static void OGRAPISpyDumpFeature( OGRFeatureH hFeat )
869 {
870 OGRFeature* poFeature = OGRFeature::FromHandle(hFeat);
871
872 fprintf(fpSpyFile, "f = ogr.Feature(%s)\n",
873 OGRAPISpyGetFeatureDefnVar(OGRFeatureDefn::ToHandle(poFeature->
874 GetDefnRef())).c_str());
875 if( poFeature->GetFID() != -1 )
876 fprintf(fpSpyFile, "f.SetFID(" CPL_FRMT_GIB ")\n", poFeature->GetFID());
877 for( int i = 0; i < poFeature->GetFieldCount(); i++ )
878 {
879 if( poFeature->IsFieldNull(i) )
880 {
881 fprintf(fpSpyFile, "f.SetFieldNull(%d)\n", i);
882 }
883 else if( poFeature->IsFieldSet(i) )
884 {
885 switch( poFeature->GetFieldDefnRef(i)->GetType())
886 {
887 case OFTInteger:
888 fprintf(fpSpyFile, "f.SetField(%d, %d)\n", i,
889 poFeature->GetFieldAsInteger(i));
890 break;
891 case OFTReal:
892 fprintf(fpSpyFile,
893 "%s", CPLSPrintf("f.SetField(%d, %.16g)\n", i,
894 poFeature->GetFieldAsDouble(i)));
895 break;
896 case OFTString:
897 fprintf(fpSpyFile, "f.SetField(%d, %s)\n", i,
898 OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str());
899 break;
900 default:
901 fprintf(fpSpyFile, "f.SetField(%d, %s) #FIXME\n", i,
902 OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str());
903 break;
904 }
905 }
906 }
907 for( int i = 0; i < poFeature->GetGeomFieldCount(); i++ )
908 {
909 OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
910 if( poGeom != nullptr )
911 {
912 fprintf(fpSpyFile, "f.SetGeomField(%d, %s)\n",
913 i,
914 OGRAPISpyGetGeom(OGRGeometry::ToHandle(poGeom)).c_str());
915 }
916 }
917 const char* pszStyleString = poFeature->GetStyleString();
918 if( pszStyleString != nullptr )
919 fprintf(fpSpyFile, "f.SetStyleString(%s)\n",
920 OGRAPISpyGetString(pszStyleString).c_str() );
921 }
922
OGRAPISpy_L_SetFeature(OGRLayerH hLayer,OGRFeatureH hFeat)923 void OGRAPISpy_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
924 {
925 CPLMutexHolderD(&hMutex);
926 OGRAPISpyFlushDefered();
927 OGRAPISpyDumpFeature(hFeat);
928 fprintf(fpSpyFile, "%s.SetFeature(f)\n",
929 OGRAPISpyGetLayerVar(hLayer).c_str());
930 // In case layer defn is changed afterwards.
931 fprintf(fpSpyFile, "f = None\n");
932 OGRAPISpyFileClose();
933 }
934
OGRAPISpy_L_CreateFeature(OGRLayerH hLayer,OGRFeatureH hFeat)935 void OGRAPISpy_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
936 {
937 CPLMutexHolderD(&hMutex);
938 OGRAPISpyFlushDefered();
939 OGRAPISpyDumpFeature(hFeat);
940 fprintf(fpSpyFile, "%s.CreateFeature(f)\n",
941 OGRAPISpyGetLayerVar(hLayer).c_str());
942 // In case layer defn is changed afterwards.
943 fprintf(fpSpyFile, "f = None\n");
944 OGRAPISpyFileClose();
945 }
946
OGRAPISpyDumpFieldDefn(OGRFieldDefn * poFieldDefn)947 static void OGRAPISpyDumpFieldDefn( OGRFieldDefn* poFieldDefn )
948 {
949 CPLMutexHolderD(&hMutex);
950 fprintf(fpSpyFile, "fd = ogr.FieldDefn(%s, %s)\n",
951 OGRAPISpyGetString(poFieldDefn->GetNameRef()).c_str(),
952 OGRAPISpyGetFieldType(poFieldDefn->GetType()).c_str());
953 if( poFieldDefn->GetWidth() > 0 )
954 fprintf(fpSpyFile, "fd.SetWidth(%d)\n", poFieldDefn->GetWidth() );
955 if( poFieldDefn->GetPrecision() > 0 )
956 fprintf(fpSpyFile, "fd.SetPrecision(%d)\n",
957 poFieldDefn->GetPrecision() );
958 if( !poFieldDefn->IsNullable() )
959 fprintf(fpSpyFile, "fd.SetNullable(0)\n");
960 if( poFieldDefn->GetDefault() != nullptr )
961 fprintf(fpSpyFile, "fd.SetDefault(%s)\n",
962 OGRAPISpyGetString(poFieldDefn->GetDefault()).c_str());
963 }
964
OGRAPISpy_L_CreateField(OGRLayerH hLayer,OGRFieldDefnH hField,int bApproxOK)965 void OGRAPISpy_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
966 int bApproxOK )
967 {
968 CPLMutexHolderD(&hMutex);
969 OGRAPISpyFlushDefered();
970 OGRFieldDefn* poFieldDefn = OGRFieldDefn::FromHandle(hField);
971 OGRAPISpyDumpFieldDefn(poFieldDefn);
972 fprintf(fpSpyFile, "%s.CreateField(fd, approx_ok=%d)\n",
973 OGRAPISpyGetLayerVar(hLayer).c_str(), bApproxOK);
974 OGRAPISpyFileClose();
975 }
976
OGRAPISpy_L_DeleteField(OGRLayerH hLayer,int iField)977 void OGRAPISpy_L_DeleteField( OGRLayerH hLayer, int iField )
978 {
979 CPLMutexHolderD(&hMutex);
980 OGRAPISpyFlushDefered();
981 fprintf(fpSpyFile, "%s.DeleteField(%d)\n",
982 OGRAPISpyGetLayerVar(hLayer).c_str(), iField);
983 OGRAPISpyFileClose();
984 }
985
OGRAPISpy_L_ReorderFields(OGRLayerH hLayer,int * panMap)986 void OGRAPISpy_L_ReorderFields( OGRLayerH hLayer, int* panMap )
987 {
988 CPLMutexHolderD(&hMutex);
989 OGRAPISpyFlushDefered();
990 OGRLayer* poLayer = OGRLayer::FromHandle(hLayer);
991 fprintf(fpSpyFile, "%s.ReorderFields([",
992 OGRAPISpyGetLayerVar(hLayer).c_str());
993 for( int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
994 {
995 if( i > 0 ) fprintf(fpSpyFile, ", ");
996 fprintf(fpSpyFile, "%d", panMap[i]);
997 }
998 fprintf(fpSpyFile, "])\n");
999 OGRAPISpyFileClose();
1000 }
1001
OGRAPISpy_L_ReorderField(OGRLayerH hLayer,int iOldFieldPos,int iNewFieldPos)1002 void OGRAPISpy_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos,
1003 int iNewFieldPos )
1004 {
1005 CPLMutexHolderD(&hMutex);
1006 OGRAPISpyFlushDefered();
1007 fprintf(fpSpyFile, "%s.ReorderField(%d, %d)\n",
1008 OGRAPISpyGetLayerVar(hLayer).c_str(), iOldFieldPos, iNewFieldPos);
1009 OGRAPISpyFileClose();
1010 }
1011
OGRAPISpy_L_AlterFieldDefn(OGRLayerH hLayer,int iField,OGRFieldDefnH hNewFieldDefn,int nFlags)1012 void OGRAPISpy_L_AlterFieldDefn( OGRLayerH hLayer, int iField,
1013 OGRFieldDefnH hNewFieldDefn, int nFlags )
1014 {
1015 CPLMutexHolderD(&hMutex);
1016 OGRAPISpyFlushDefered();
1017 OGRFieldDefn* poFieldDefn = OGRFieldDefn::FromHandle(hNewFieldDefn);
1018 OGRAPISpyDumpFieldDefn(poFieldDefn);
1019 fprintf(fpSpyFile, "%s.AlterFieldDefn(%d, fd, %d)\n",
1020 OGRAPISpyGetLayerVar(hLayer).c_str(), iField, nFlags);
1021 OGRAPISpyFileClose();
1022 }
1023
OGRAPISpy_L_CreateGeomField(OGRLayerH hLayer,OGRGeomFieldDefnH hField,int bApproxOK)1024 void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
1025 int bApproxOK )
1026 {
1027 CPLMutexHolderD(&hMutex);
1028 OGRAPISpyFlushDefered();
1029 OGRGeomFieldDefn* poGeomFieldDefn = OGRGeomFieldDefn::FromHandle(hField);
1030
1031 fprintf(fpSpyFile, "geom_fd = ogr.GeomFieldDefn(%s, %s)\n",
1032 OGRAPISpyGetString(poGeomFieldDefn->GetNameRef()).c_str(),
1033 OGRAPISpyGetGeomType(poGeomFieldDefn->GetType()).c_str());
1034 if( poGeomFieldDefn->GetSpatialRef() != nullptr )
1035 fprintf(
1036 fpSpyFile, "geom_fd.SetSpatialRef(%s)\n",
1037 OGRAPISpyGetSRS(
1038 OGRSpatialReference::ToHandle
1039 (poGeomFieldDefn->GetSpatialRef())).c_str() );
1040 if( !poGeomFieldDefn->IsNullable() )
1041 fprintf(fpSpyFile, "geom_fd.SetNullable(0)\n");
1042 fprintf(fpSpyFile, "%s.CreateGeomField(geom_fd, approx_ok=%d)\n",
1043 OGRAPISpyGetLayerVar(hLayer).c_str(), bApproxOK);
1044 OGRAPISpyFileClose();
1045 }
1046
OGRAPISpy_L_Op(OGRLayerH hLayer,const char * pszMethod)1047 static void OGRAPISpy_L_Op( OGRLayerH hLayer, const char* pszMethod )
1048 {
1049 CPLMutexHolderD(&hMutex);
1050 OGRAPISpyFlushDefered();
1051 fprintf(fpSpyFile, "%s.%s()\n",
1052 OGRAPISpyGetLayerVar(hLayer).c_str(), pszMethod);
1053 OGRAPISpyFileClose();
1054 }
1055
OGRAPISpy_L_StartTransaction(OGRLayerH hLayer)1056 void OGRAPISpy_L_StartTransaction( OGRLayerH hLayer )
1057 { OGRAPISpy_L_Op(hLayer, "StartTransaction"); }
OGRAPISpy_L_CommitTransaction(OGRLayerH hLayer)1058 void OGRAPISpy_L_CommitTransaction( OGRLayerH hLayer )
1059 { OGRAPISpy_L_Op(hLayer, "CommitTransaction"); }
OGRAPISpy_L_RollbackTransaction(OGRLayerH hLayer)1060 void OGRAPISpy_L_RollbackTransaction( OGRLayerH hLayer )
1061 { OGRAPISpy_L_Op(hLayer, "RollbackTransaction"); }
1062
OGRAPISpy_L_GetLayerDefn(OGRLayerH hLayer)1063 void OGRAPISpy_L_GetLayerDefn( OGRLayerH hLayer )
1064 {
1065 if( hLayer != hLayerGetLayerDefn )
1066 {
1067 OGRAPISpyFlushDefered();
1068 hLayerGetLayerDefn = hLayer;
1069 OGRAPISpyFileClose();
1070 }
1071 }
1072
OGRAPISpy_L_GetSpatialRef(OGRLayerH hLayer)1073 void OGRAPISpy_L_GetSpatialRef( OGRLayerH hLayer )
1074 { OGRAPISpy_L_Op(hLayer, "GetSpatialRef"); }
OGRAPISpy_L_GetSpatialFilter(OGRLayerH hLayer)1075 void OGRAPISpy_L_GetSpatialFilter( OGRLayerH hLayer )
1076 { OGRAPISpy_L_Op(hLayer, "GetSpatialFilter"); }
OGRAPISpy_L_ResetReading(OGRLayerH hLayer)1077 void OGRAPISpy_L_ResetReading( OGRLayerH hLayer )
1078 { OGRAPISpy_L_Op(hLayer, "ResetReading"); }
OGRAPISpy_L_SyncToDisk(OGRLayerH hLayer)1079 void OGRAPISpy_L_SyncToDisk( OGRLayerH hLayer )
1080 { OGRAPISpy_L_Op(hLayer, "SyncToDisk"); }
OGRAPISpy_L_GetFIDColumn(OGRLayerH hLayer)1081 void OGRAPISpy_L_GetFIDColumn( OGRLayerH hLayer )
1082 { OGRAPISpy_L_Op(hLayer, "GetFIDColumn"); }
OGRAPISpy_L_GetGeometryColumn(OGRLayerH hLayer)1083 void OGRAPISpy_L_GetGeometryColumn( OGRLayerH hLayer )
1084 { OGRAPISpy_L_Op(hLayer, "GetGeometryColumn"); }
OGRAPISpy_L_GetName(OGRLayerH hLayer)1085 void OGRAPISpy_L_GetName( OGRLayerH hLayer )
1086 { OGRAPISpy_L_Op(hLayer, "GetName"); }
OGRAPISpy_L_GetGeomType(OGRLayerH hLayer)1087 void OGRAPISpy_L_GetGeomType( OGRLayerH hLayer )
1088 { OGRAPISpy_L_Op(hLayer, "GetGeomType"); }
1089
OGRAPISpy_L_FindFieldIndex(OGRLayerH hLayer,const char * pszFieldName,int bExactMatch)1090 void OGRAPISpy_L_FindFieldIndex( OGRLayerH hLayer, const char *pszFieldName,
1091 int bExactMatch )
1092 {
1093 CPLMutexHolderD(&hMutex);
1094 OGRAPISpyFlushDefered();
1095 fprintf(fpSpyFile, "%s.FindFieldIndex(%s, %d)\n",
1096 OGRAPISpyGetLayerVar(hLayer).c_str(),
1097 OGRAPISpyGetString(pszFieldName).c_str(), bExactMatch);
1098 OGRAPISpyFileClose();
1099 }
1100
OGRAPISpy_L_TestCapability(OGRLayerH hLayer,const char * pszCap)1101 void OGRAPISpy_L_TestCapability( OGRLayerH hLayer, const char* pszCap )
1102 {
1103 CPLMutexHolderD(&hMutex);
1104 OGRAPISpyFlushDefered();
1105 fprintf(fpSpyFile, "%s.TestCapability(%s)\n",
1106 OGRAPISpyGetLayerVar(hLayer).c_str(),
1107 OGRAPISpyGetString(pszCap).c_str());
1108 OGRAPISpyFileClose();
1109 }
1110
OGRAPISpy_L_SetSpatialFilter(OGRLayerH hLayer,OGRGeometryH hGeom)1111 void OGRAPISpy_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
1112 {
1113 CPLMutexHolderD(&hMutex);
1114 OGRAPISpyFlushDefered();
1115 fprintf(fpSpyFile, "%s.SetSpatialFilter(%s)\n",
1116 OGRAPISpyGetLayerVar(hLayer).c_str(),
1117 OGRAPISpyGetGeom(hGeom).c_str());
1118 OGRAPISpyFileClose();
1119 }
1120
OGRAPISpy_L_SetSpatialFilterEx(OGRLayerH hLayer,int iGeomField,OGRGeometryH hGeom)1121 void OGRAPISpy_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
1122 OGRGeometryH hGeom )
1123 {
1124 CPLMutexHolderD(&hMutex);
1125 OGRAPISpyFlushDefered();
1126 fprintf(fpSpyFile, "%s.SetSpatialFilter(%d, %s)\n",
1127 OGRAPISpyGetLayerVar(hLayer).c_str(),
1128 iGeomField,
1129 OGRAPISpyGetGeom(hGeom).c_str());
1130 OGRAPISpyFileClose();
1131 }
1132
OGRAPISpy_L_SetSpatialFilterRect(OGRLayerH hLayer,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1133 void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
1134 double dfMinX, double dfMinY,
1135 double dfMaxX, double dfMaxY )
1136 {
1137 CPLMutexHolderD(&hMutex);
1138 OGRAPISpyFlushDefered();
1139 fprintf(fpSpyFile, "%s",
1140 CPLSPrintf("%s.SetSpatialFilterRect(%.16g, %.16g, %.16g, %.16g)\n",
1141 OGRAPISpyGetLayerVar(hLayer).c_str(),
1142 dfMinX, dfMinY, dfMaxX, dfMaxY));
1143 OGRAPISpyFileClose();
1144 }
1145
OGRAPISpy_L_SetSpatialFilterRectEx(OGRLayerH hLayer,int iGeomField,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1146 void OGRAPISpy_L_SetSpatialFilterRectEx( OGRLayerH hLayer, int iGeomField,
1147 double dfMinX, double dfMinY,
1148 double dfMaxX, double dfMaxY )
1149 {
1150 CPLMutexHolderD(&hMutex);
1151 OGRAPISpyFlushDefered();
1152 fprintf(fpSpyFile, "%s", CPLSPrintf("%s.SetSpatialFilterRect(%d, "
1153 "%.16g, %.16g, %.16g, %.16g)\n",
1154 OGRAPISpyGetLayerVar(hLayer).c_str(),
1155 iGeomField,
1156 dfMinX, dfMinY, dfMaxX, dfMaxY));
1157 OGRAPISpyFileClose();
1158 }
1159
OGRAPISpy_L_DeleteFeature(OGRLayerH hLayer,GIntBig nFID)1160 void OGRAPISpy_L_DeleteFeature( OGRLayerH hLayer, GIntBig nFID )
1161 {
1162 CPLMutexHolderD(&hMutex);
1163 OGRAPISpyFlushDefered();
1164 fprintf(fpSpyFile, "%s.DeleteFeature(" CPL_FRMT_GIB ")\n",
1165 OGRAPISpyGetLayerVar(hLayer).c_str(), nFID);
1166 OGRAPISpyFileClose();
1167 }
1168
OGRAPISpy_L_SetIgnoredFields(OGRLayerH hLayer,const char ** papszIgnoredFields)1169 void OGRAPISpy_L_SetIgnoredFields( OGRLayerH hLayer,
1170 const char** papszIgnoredFields )
1171 {
1172 CPLMutexHolderD(&hMutex);
1173 OGRAPISpyFlushDefered();
1174 fprintf(fpSpyFile, "%s.SetIgnoredFields(%s)\n",
1175 OGRAPISpyGetLayerVar(hLayer).c_str(),
1176 OGRAPISpyGetOptions(
1177 const_cast<char **>(papszIgnoredFields)).c_str());
1178 OGRAPISpyFileClose();
1179 }
1180
OGRAPISpy_FD_GetGeomType(OGRFeatureDefnH hDefn)1181 void OGRAPISpy_FD_GetGeomType( OGRFeatureDefnH hDefn )
1182 {
1183 CPLMutexHolderD(&hMutex);
1184 OGRAPISpyFlushDefered();
1185 fprintf(fpSpyFile, "%s.GetGeomType()\n",
1186 OGRAPISpyGetFeatureDefnVar(hDefn).c_str());
1187 OGRAPISpyFileClose();
1188 }
1189
OGRAPISpy_FD_GetFieldCount(OGRFeatureDefnH hDefn)1190 void OGRAPISpy_FD_GetFieldCount( OGRFeatureDefnH hDefn )
1191 {
1192 CPLMutexHolderD(&hMutex);
1193 if( hLayerGetLayerDefn != nullptr &&
1194 OGRFeatureDefn::ToHandle(
1195 OGRLayer::FromHandle(hLayerGetLayerDefn)->GetLayerDefn()) ==
1196 hDefn )
1197 {
1198 bDeferGetFieldCount = true;
1199 }
1200 else
1201 {
1202 OGRAPISpyFlushDefered();
1203 fprintf(fpSpyFile, "%s.GetFieldCount()\n",
1204 OGRAPISpyGetFeatureDefnVar(hDefn).c_str());
1205 OGRAPISpyFileClose();
1206 }
1207 }
1208
OGRAPISpy_FD_GetFieldDefn(OGRFeatureDefnH hDefn,int iField,OGRFieldDefnH hField)1209 void OGRAPISpy_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField,
1210 OGRFieldDefnH hField )
1211 {
1212 CPLMutexHolderD(&hMutex);
1213 OGRAPISpyFlushDefered();
1214 fprintf(fpSpyFile, "%s_fielddefn%d = %s.GetFieldDefn(%d)\n",
1215 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1216 iField,
1217 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1218 iField);
1219
1220 std::map<OGRFieldDefnH, CPLString>::iterator oIter =
1221 oGlobalMapFieldDefn.find(hField);
1222 if( oIter == oGlobalMapFieldDefn.end() )
1223 {
1224 oMapFDefn[hDefn].oMapFieldDefn[hField] = iField;
1225 oGlobalMapFieldDefn[hField] =
1226 CPLSPrintf("%s_fielddefn%d",
1227 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1228 iField);
1229 }
1230
1231 OGRAPISpyFileClose();
1232 }
1233
OGRAPISpy_FD_GetFieldIndex(OGRFeatureDefnH hDefn,const char * pszFieldName)1234 void OGRAPISpy_FD_GetFieldIndex( OGRFeatureDefnH hDefn,
1235 const char* pszFieldName )
1236 {
1237 CPLMutexHolderD(&hMutex);
1238 OGRAPISpyFlushDefered();
1239 fprintf(fpSpyFile, "%s.GetFieldIndex(%s)\n",
1240 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1241 OGRAPISpyGetString(pszFieldName).c_str());
1242 OGRAPISpyFileClose();
1243 }
1244
OGRAPISpy_Fld_GetXXXX(OGRFieldDefnH hField,const char * pszOp)1245 void OGRAPISpy_Fld_GetXXXX( OGRFieldDefnH hField, const char* pszOp )
1246 {
1247 CPLMutexHolderD(&hMutex);
1248 OGRAPISpyFlushDefered();
1249 fprintf(fpSpyFile, "%s.%s()\n",
1250 oGlobalMapFieldDefn[hField].c_str(), pszOp);
1251 OGRAPISpyFileClose();
1252 }
1253
OGRAPISpy_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)1254 void OGRAPISpy_FD_GetGeomFieldCount( OGRFeatureDefnH hDefn )
1255 {
1256 CPLMutexHolderD(&hMutex);
1257 OGRAPISpyFlushDefered();
1258 fprintf(fpSpyFile, "%s.GetGeomFieldCount()\n",
1259 OGRAPISpyGetFeatureDefnVar(hDefn).c_str());
1260 OGRAPISpyFileClose();
1261 }
1262
OGRAPISpy_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn,int iGeomField,OGRGeomFieldDefnH hGeomField)1263 void OGRAPISpy_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField,
1264 OGRGeomFieldDefnH hGeomField )
1265 {
1266 CPLMutexHolderD(&hMutex);
1267 OGRAPISpyFlushDefered();
1268 fprintf(fpSpyFile, "%s_geomfielddefn%d = %s.GetGeomFieldDefn(%d)\n",
1269 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1270 iGeomField,
1271 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1272 iGeomField);
1273
1274 std::map<OGRGeomFieldDefnH, CPLString>::iterator oIter =
1275 oGlobalMapGeomFieldDefn.find(hGeomField);
1276 if( oIter == oGlobalMapGeomFieldDefn.end() )
1277 {
1278 oMapFDefn[hDefn].oMapGeomFieldDefn[hGeomField] = iGeomField;
1279 oGlobalMapGeomFieldDefn[hGeomField] =
1280 CPLSPrintf("%s_geomfielddefn%d",
1281 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1282 iGeomField);
1283 }
1284
1285 OGRAPISpyFileClose();
1286 }
1287
OGRAPISpy_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn,const char * pszFieldName)1288 void OGRAPISpy_FD_GetGeomFieldIndex( OGRFeatureDefnH hDefn,
1289 const char* pszFieldName )
1290 {
1291 CPLMutexHolderD(&hMutex);
1292 OGRAPISpyFlushDefered();
1293 fprintf(fpSpyFile, "%s.GetGeomFieldIndex(%s)\n",
1294 OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
1295 OGRAPISpyGetString(pszFieldName).c_str());
1296 OGRAPISpyFileClose();
1297 }
1298
OGRAPISpy_GFld_GetXXXX(OGRGeomFieldDefnH hGeomField,const char * pszOp)1299 void OGRAPISpy_GFld_GetXXXX( OGRGeomFieldDefnH hGeomField, const char* pszOp )
1300 {
1301 CPLMutexHolderD(&hMutex);
1302 OGRAPISpyFlushDefered();
1303 fprintf(fpSpyFile, "%s.%s()\n",
1304 oGlobalMapGeomFieldDefn[hGeomField].c_str(), pszOp);
1305 OGRAPISpyFileClose();
1306 }
1307
OGRAPISPYCPLSetConfigOption(const char * pszKey,const char * pszValue)1308 void OGRAPISPYCPLSetConfigOption(const char* pszKey, const char* pszValue )
1309 {
1310 if( STARTS_WITH(pszKey, "OGR_API_SPY_") || STARTS_WITH(pszKey, "__") )
1311 return;
1312 if( !OGRAPISpyEnabled() )
1313 return;
1314 OGRAPISpyFlushDefered();
1315 if( pszValue )
1316 {
1317 fprintf(fpSpyFile, "gdal.SetConfigOption(%s, %s)\n",
1318 OGRAPISpyGetString(pszKey).c_str(),
1319 OGRAPISpyGetString(pszValue).c_str());
1320 }
1321 else
1322 {
1323 fprintf(fpSpyFile, "gdal.SetConfigOption(%s, None)\n",
1324 OGRAPISpyGetString(pszKey).c_str());
1325 }
1326 OGRAPISpyFileClose();
1327 }
1328
OGRAPISPYCPLSetThreadLocalConfigOption(const char * pszKey,const char * pszValue)1329 void OGRAPISPYCPLSetThreadLocalConfigOption(const char* pszKey, const char* pszValue )
1330 {
1331 if( STARTS_WITH(pszKey, "OGR_API_SPY_") || STARTS_WITH(pszKey, "__") )
1332 return;
1333 if( !OGRAPISpyEnabled() )
1334 return;
1335 OGRAPISpyFlushDefered();
1336 if( pszValue )
1337 {
1338 fprintf(fpSpyFile, "gdal.SetConfigOption(%s, %s) # SetThreadLocalConfigOption actually\n",
1339 OGRAPISpyGetString(pszKey).c_str(),
1340 OGRAPISpyGetString(pszValue).c_str());
1341 }
1342 else
1343 {
1344 fprintf(fpSpyFile, "gdal.SetConfigOption(%s, None) # SetThreadLocalConfigOption actually\n",
1345 OGRAPISpyGetString(pszKey).c_str());
1346 }
1347 OGRAPISpyFileClose();
1348 }
1349
1350 #endif // OGRAPISPY_ENABLED
1351