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