Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRGeoconceptDriver class.
5 : * Author: Didier Richard, didier.richard@ign.fr
6 : * Language: C++
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Geoconcept and IGN
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogrgeoconceptdatasource.h"
17 :
18 : /************************************************************************/
19 : /* Open() */
20 : /************************************************************************/
21 :
22 25031 : static GDALDataset *OGRGeoconceptDriverOpen(GDALOpenInfo *poOpenInfo)
23 :
24 : {
25 25031 : const char *pszFilename = poOpenInfo->pszFilename;
26 : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
27 : /* -------------------------------------------------------------------- */
28 : /* We will only consider .gxt and .txt files. */
29 : /* -------------------------------------------------------------------- */
30 50062 : const std::string osExtension = CPLGetExtensionSafe(pszFilename);
31 50057 : if (!EQUAL(osExtension.c_str(), "gxt") &&
32 25026 : !EQUAL(osExtension.c_str(), "txt"))
33 : {
34 25015 : return nullptr;
35 : }
36 : #endif
37 :
38 16 : auto poDS = new OGRGeoconceptDataSource();
39 :
40 16 : if (!poDS->Open(pszFilename, true, poOpenInfo->eAccess == GA_Update))
41 : {
42 8 : delete poDS;
43 8 : return nullptr;
44 : }
45 8 : return poDS;
46 : }
47 :
48 : /************************************************************************/
49 : /* CreateDataSource() */
50 : /* */
51 : /* Options (-dsco) : */
52 : /* EXTENSION=GXT|TXT (default GXT) */
53 : /************************************************************************/
54 :
55 18 : static GDALDataset *OGRGeoconceptDriverCreate(const char *pszName,
56 : int /* nXSize */,
57 : int /* nYSize */,
58 : int /* nBandCount */,
59 : GDALDataType, char **papszOptions)
60 :
61 : {
62 : VSIStatBufL sStat;
63 : /* int bSingleNewFile = FALSE; */
64 :
65 18 : if (pszName == nullptr || strlen(pszName) == 0)
66 : {
67 0 : CPLError(CE_Failure, CPLE_AppDefined,
68 : "Invalid datasource name (null or empty)");
69 0 : return nullptr;
70 : }
71 :
72 : /* -------------------------------------------------------------------- */
73 : /* Is the target a valid existing directory? */
74 : /* -------------------------------------------------------------------- */
75 18 : if (VSIStatL(pszName, &sStat) == 0)
76 : {
77 0 : if (!VSI_ISDIR(sStat.st_mode))
78 : {
79 0 : CPLError(CE_Failure, CPLE_AppDefined,
80 : "%s is not a valid existing directory.", pszName);
81 0 : return nullptr;
82 : }
83 : }
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Does it end with the extension .gxt indicating the user likely */
87 : /* wants to create a single file set? */
88 : /* -------------------------------------------------------------------- */
89 53 : else if (EQUAL(CPLGetExtensionSafe(pszName).c_str(), "gxt") ||
90 35 : EQUAL(CPLGetExtensionSafe(pszName).c_str(), "txt"))
91 : {
92 : /* bSingleNewFile = TRUE; */
93 : }
94 :
95 : /* -------------------------------------------------------------------- */
96 : /* Return a new OGRDataSource() */
97 : /* -------------------------------------------------------------------- */
98 18 : OGRGeoconceptDataSource *poDS = new OGRGeoconceptDataSource();
99 18 : if (!poDS->Create(pszName, papszOptions))
100 : {
101 1 : delete poDS;
102 1 : return nullptr;
103 : }
104 17 : return poDS;
105 : }
106 :
107 : /************************************************************************/
108 : /* OGRGeoconceptDriverDelete() */
109 : /************************************************************************/
110 :
111 16 : static CPLErr OGRGeoconceptDriverDelete(const char *pszDataSource)
112 :
113 : {
114 : VSIStatBufL sStatBuf;
115 : static const char *const apszExtensions[] = {"gxt", "txt", "gct",
116 : "gcm", "gcr", nullptr};
117 :
118 16 : if (VSIStatL(pszDataSource, &sStatBuf) != 0)
119 : {
120 0 : CPLError(CE_Failure, CPLE_AppDefined,
121 : "%s does not appear to be a file or directory.",
122 : pszDataSource);
123 :
124 0 : return CE_Failure;
125 : }
126 :
127 16 : if (VSI_ISREG(sStatBuf.st_mode) &&
128 16 : (EQUAL(CPLGetExtensionSafe(pszDataSource).c_str(), "gxt") ||
129 16 : EQUAL(CPLGetExtensionSafe(pszDataSource).c_str(), "txt")))
130 : {
131 0 : for (int iExt = 0; apszExtensions[iExt] != nullptr; iExt++)
132 : {
133 : const std::string osFile =
134 0 : CPLResetExtensionSafe(pszDataSource, apszExtensions[iExt]);
135 0 : if (VSIStatL(osFile.c_str(), &sStatBuf) == 0)
136 0 : VSIUnlink(osFile.c_str());
137 : }
138 : }
139 16 : else if (VSI_ISDIR(sStatBuf.st_mode))
140 : {
141 16 : char **papszDirEntries = VSIReadDir(pszDataSource);
142 :
143 32 : for (int iFile = 0;
144 32 : papszDirEntries != nullptr && papszDirEntries[iFile] != nullptr;
145 : iFile++)
146 : {
147 16 : if (CSLFindString(
148 : const_cast<char **>(apszExtensions),
149 32 : CPLGetExtensionSafe(papszDirEntries[iFile]).c_str()) != -1)
150 : {
151 16 : VSIUnlink(CPLFormFilenameSafe(pszDataSource,
152 16 : papszDirEntries[iFile], nullptr)
153 : .c_str());
154 : }
155 : }
156 :
157 16 : CSLDestroy(papszDirEntries);
158 :
159 16 : VSIRmdir(pszDataSource);
160 : }
161 :
162 16 : return CE_None;
163 : }
164 :
165 : /************************************************************************/
166 : /* RegisterOGRGeoconcept() */
167 : /************************************************************************/
168 :
169 1682 : void RegisterOGRGeoconcept()
170 :
171 : {
172 1682 : if (GDALGetDriverByName("Geoconcept"))
173 301 : return;
174 :
175 1381 : GDALDriver *poDriver = new GDALDriver();
176 1381 : poDriver->SetDescription("Geoconcept");
177 1381 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Geoconcept");
178 1381 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
179 1381 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
180 1381 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
181 1381 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "gxt txt");
182 1381 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
183 :
184 1381 : poDriver->SetMetadataItem(
185 : GDAL_DMD_CREATIONOPTIONLIST,
186 : "<CreationOptionList>"
187 : " <Option name='EXTENSION' type='string-select' "
188 : "description='indicates the "
189 : "GeoConcept export file extension. TXT was used by earlier releases of "
190 : "GeoConcept. GXT is currently used.' default='GXT'>"
191 : " <Value>GXT</Value>"
192 : " <Value>TXT</Value>"
193 : " </Option>"
194 : " <Option name='CONFIG' type='string' description='path to the GCT "
195 : "file that "
196 : "describes the GeoConcept types definitions.'/>"
197 1381 : "</CreationOptionList>");
198 :
199 1381 : poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
200 : "<LayerCreationOptionList>"
201 : " <Option name='FEATURETYPE' type='string' "
202 : "description='TYPE.SUBTYPE : "
203 : "defines the feature to be created. The TYPE "
204 : "corresponds to one of the Name "
205 : "found in the GCT file for a type section. The "
206 : "SUBTYPE corresponds to one of "
207 : "the Name found in the GCT file for a sub-type "
208 : "section within the previous "
209 : "type section'/>"
210 1381 : "</LayerCreationOptionList>");
211 1381 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
212 1381 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
213 :
214 1381 : poDriver->pfnOpen = OGRGeoconceptDriverOpen;
215 1381 : poDriver->pfnCreate = OGRGeoconceptDriverCreate;
216 1381 : poDriver->pfnDelete = OGRGeoconceptDriverDelete;
217 :
218 1381 : GetGDALDriverManager()->RegisterDriver(poDriver);
219 : }
|