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