1 : /******************************************************************************
2 : * $Id: ogrcsvdatasource.cpp 23244 2011-10-16 21:52:16Z rouault $
3 : *
4 : * Project: CSV Translator
5 : * Purpose: Implements OGRCSVDataSource class
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_csv.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "cpl_csv.h"
34 : #include "cpl_vsi_virtual.h"
35 :
36 : CPL_CVSID("$Id: ogrcsvdatasource.cpp 23244 2011-10-16 21:52:16Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRCSVDataSource() */
40 : /************************************************************************/
41 :
42 1206 : OGRCSVDataSource::OGRCSVDataSource()
43 :
44 : {
45 1206 : papoLayers = NULL;
46 1206 : nLayers = 0;
47 :
48 1206 : pszName = NULL;
49 :
50 1206 : bUpdate = FALSE;
51 1206 : }
52 :
53 : /************************************************************************/
54 : /* ~OGRCSVDataSource() */
55 : /************************************************************************/
56 :
57 1206 : OGRCSVDataSource::~OGRCSVDataSource()
58 :
59 : {
60 1422 : for( int i = 0; i < nLayers; i++ )
61 216 : delete papoLayers[i];
62 1206 : CPLFree( papoLayers );
63 :
64 1206 : CPLFree( pszName );
65 1206 : }
66 :
67 : /************************************************************************/
68 : /* TestCapability() */
69 : /************************************************************************/
70 :
71 10 : int OGRCSVDataSource::TestCapability( const char * pszCap )
72 :
73 : {
74 10 : if( EQUAL(pszCap,ODsCCreateLayer) )
75 6 : return bUpdate;
76 4 : else if( EQUAL(pszCap,ODsCDeleteLayer) )
77 4 : return bUpdate;
78 : else
79 0 : return FALSE;
80 : }
81 :
82 : /************************************************************************/
83 : /* GetLayer() */
84 : /************************************************************************/
85 :
86 286 : OGRLayer *OGRCSVDataSource::GetLayer( int iLayer )
87 :
88 : {
89 286 : if( iLayer < 0 || iLayer >= nLayers )
90 0 : return NULL;
91 : else
92 286 : return papoLayers[iLayer];
93 : }
94 :
95 : /************************************************************************/
96 : /* Open() */
97 : /************************************************************************/
98 :
99 1206 : int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
100 : int bForceOpen )
101 :
102 : {
103 1206 : pszName = CPLStrdup( pszFilename );
104 1206 : bUpdate = bUpdateIn;
105 :
106 1206 : if (bUpdateIn && bForceOpen && EQUAL(pszFilename, "/vsistdout/"))
107 2 : return TRUE;
108 :
109 : /* For writable /vsizip/, do nothing more */
110 1204 : if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0)
111 0 : return TRUE;
112 :
113 1204 : CPLString osFilename(pszFilename);
114 1204 : CPLString osBaseFilename = CPLGetFilename(pszFilename);
115 1204 : CPLString osExt = CPLGetExtension(osFilename);
116 1204 : pszFilename = NULL;
117 :
118 1204 : int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4);
119 1204 : int bUSGeonamesFile = FALSE;
120 1204 : int bGeonamesOrgFile = FALSE;
121 1204 : if (bIgnoreExtension)
122 : {
123 0 : osFilename = osFilename + 4;
124 : }
125 :
126 : /* Those are *not* real .XLS files, but text file with tab as column separator */
127 1204 : if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
128 : EQUAL(osBaseFilename, "NfdcRunways.xls") ||
129 : EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
130 : EQUAL(osBaseFilename, "NfdcSchedules.xls"))
131 : {
132 0 : if (bUpdateIn)
133 0 : return FALSE;
134 0 : bIgnoreExtension = TRUE;
135 : }
136 1204 : else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
137 : EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
138 : EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
139 : EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
140 : EQUALN(osBaseFilename, "AllNames_", 9) ||
141 : EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
142 : EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
143 : EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
144 : EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
145 : EQUALN(osBaseFilename, "AllStates_", 10) ||
146 : EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
147 : (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
148 : (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
149 : (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
150 : {
151 0 : if (bUpdateIn)
152 0 : return FALSE;
153 0 : bIgnoreExtension = TRUE;
154 0 : bUSGeonamesFile = TRUE;
155 :
156 0 : if (EQUAL(osExt, "zip") &&
157 : strstr(osFilename, "/vsizip/") == NULL )
158 : {
159 0 : osFilename = "/vsizip/" + osFilename;
160 : }
161 : }
162 1204 : else if (EQUAL(osBaseFilename, "allCountries.txt") ||
163 : EQUAL(osBaseFilename, "allCountries.zip"))
164 : {
165 0 : if (bUpdateIn)
166 0 : return FALSE;
167 0 : bIgnoreExtension = TRUE;
168 0 : bGeonamesOrgFile = TRUE;
169 :
170 0 : if (EQUAL(osExt, "zip") &&
171 : strstr(osFilename, "/vsizip/") == NULL )
172 : {
173 0 : osFilename = "/vsizip/" + osFilename;
174 : }
175 : }
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Determine what sort of object this is. */
179 : /* -------------------------------------------------------------------- */
180 : VSIStatBufL sStatBuf;
181 :
182 1204 : if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
183 342 : return FALSE;
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Is this a single CSV file? */
187 : /* -------------------------------------------------------------------- */
188 862 : if( VSI_ISREG(sStatBuf.st_mode)
189 : && (bIgnoreExtension || EQUAL(osExt,"csv")) )
190 : {
191 146 : if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls"))
192 : {
193 0 : return OpenTable( osFilename, "ARP");
194 : }
195 146 : else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls"))
196 : {
197 0 : OpenTable( osFilename, "BaseEndPhysical");
198 0 : OpenTable( osFilename, "BaseEndDisplaced");
199 0 : OpenTable( osFilename, "ReciprocalEndPhysical");
200 0 : OpenTable( osFilename, "ReciprocalEndDisplaced");
201 0 : return nLayers != 0;
202 : }
203 146 : else if (bUSGeonamesFile)
204 : {
205 : /* GNIS specific */
206 0 : if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
207 : EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
208 : EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
209 : (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10)))
210 : {
211 0 : OpenTable( osFilename, NULL, "PRIMARY");
212 : }
213 0 : else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
214 : EQUALN(osBaseFilename, "Feature_Description_History_", 28))
215 : {
216 0 : OpenTable( osFilename, NULL, "");
217 : }
218 : else
219 : {
220 0 : OpenTable( osFilename, NULL, "PRIM");
221 0 : OpenTable( osFilename, NULL, "SOURCE");
222 : }
223 0 : return nLayers != 0;
224 : }
225 :
226 146 : return OpenTable( osFilename );
227 : }
228 :
229 : /* -------------------------------------------------------------------- */
230 : /* Is this a single a ZIP file with only a CSV file inside ? */
231 : /* -------------------------------------------------------------------- */
232 716 : if( strncmp(osFilename, "/vsizip/", 8) == 0 &&
233 : EQUAL(osExt, "zip") &&
234 : VSI_ISREG(sStatBuf.st_mode) )
235 : {
236 0 : char** papszFiles = VSIReadDir(osFilename);
237 0 : if (CSLCount(papszFiles) != 1 ||
238 0 : !EQUAL(CPLGetExtension(papszFiles[0]), "CSV"))
239 : {
240 0 : CSLDestroy(papszFiles);
241 0 : return FALSE;
242 : }
243 0 : CPLString osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
244 0 : CSLDestroy(papszFiles);
245 0 : return OpenTable( osFilename );
246 : }
247 :
248 : /* -------------------------------------------------------------------- */
249 : /* Otherwise it has to be a directory. */
250 : /* -------------------------------------------------------------------- */
251 716 : if( !VSI_ISDIR(sStatBuf.st_mode) )
252 668 : return FALSE;
253 :
254 : /* -------------------------------------------------------------------- */
255 : /* Scan through for entries ending in .csv. */
256 : /* -------------------------------------------------------------------- */
257 48 : int nNotCSVCount = 0, i;
258 48 : char **papszNames = CPLReadDir( osFilename );
259 :
260 48 : for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
261 : {
262 : CPLString oSubFilename =
263 2296 : CPLFormFilename( osFilename, papszNames[i], NULL );
264 :
265 2296 : if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
266 84 : continue;
267 :
268 2212 : if (EQUAL(CPLGetExtension(oSubFilename),"csvt"))
269 26 : continue;
270 :
271 2186 : if( VSIStatL( oSubFilename, &sStatBuf ) != 0
272 : || !VSI_ISREG(sStatBuf.st_mode) )
273 : {
274 4 : nNotCSVCount++;
275 4 : continue;
276 : }
277 :
278 2182 : if (EQUAL(CPLGetExtension(oSubFilename),"csv"))
279 : {
280 46 : if( !OpenTable( oSubFilename ) )
281 : {
282 0 : CSLDestroy( papszNames );
283 0 : nNotCSVCount++;
284 0 : return FALSE;
285 : }
286 : }
287 :
288 : /* GNIS specific */
289 4272 : else if ( strlen(papszNames[i]) > 2 &&
290 2136 : EQUALN(papszNames[i]+2, "_Features_", 10) &&
291 0 : EQUAL(CPLGetExtension(papszNames[i]), "txt") )
292 : {
293 0 : int bRet = OpenTable( oSubFilename, NULL, "PRIM");
294 0 : bRet |= OpenTable( oSubFilename, NULL, "SOURCE");
295 0 : if ( !bRet )
296 : {
297 0 : CSLDestroy( papszNames );
298 0 : nNotCSVCount++;
299 0 : return FALSE;
300 : }
301 : }
302 : /* GNIS specific */
303 4272 : else if ( strlen(papszNames[i]) > 2 &&
304 2136 : EQUALN(papszNames[i]+2, "_FedCodes_", 10) &&
305 0 : EQUAL(CPLGetExtension(papszNames[i]), "txt") )
306 : {
307 0 : if ( !OpenTable( oSubFilename, NULL, "PRIMARY") )
308 : {
309 0 : CSLDestroy( papszNames );
310 0 : nNotCSVCount++;
311 0 : return FALSE;
312 : }
313 : }
314 : else
315 : {
316 2136 : nNotCSVCount++;
317 2136 : continue;
318 : }
319 : }
320 :
321 48 : CSLDestroy( papszNames );
322 :
323 : /* -------------------------------------------------------------------- */
324 : /* We presume that this is indeed intended to be a CSV */
325 : /* datasource if over half the files were .csv files. */
326 : /* -------------------------------------------------------------------- */
327 48 : return bForceOpen || nNotCSVCount < nLayers;
328 : }
329 :
330 : /************************************************************************/
331 : /* OpenTable() */
332 : /************************************************************************/
333 :
334 192 : int OGRCSVDataSource::OpenTable( const char * pszFilename,
335 : const char* pszNfdcRunwaysGeomField,
336 : const char* pszGeonamesGeomFieldPrefix)
337 :
338 : {
339 : /* -------------------------------------------------------------------- */
340 : /* Open the file. */
341 : /* -------------------------------------------------------------------- */
342 : VSILFILE * fp;
343 :
344 192 : if( bUpdate )
345 28 : fp = VSIFOpenL( pszFilename, "rb+" );
346 : else
347 164 : fp = VSIFOpenL( pszFilename, "rb" );
348 192 : if( fp == NULL )
349 : {
350 : CPLError( CE_Warning, CPLE_OpenFailed,
351 : "Failed to open %s, %s.",
352 0 : pszFilename, VSIStrerror( errno ) );
353 0 : return FALSE;
354 : }
355 :
356 192 : if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL &&
357 : strstr(pszFilename, "/vsizip/") == NULL )
358 164 : fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
359 :
360 : /* -------------------------------------------------------------------- */
361 : /* Read and parse a line. Did we get multiple fields? */
362 : /* -------------------------------------------------------------------- */
363 :
364 192 : const char* pszLine = CPLReadLineL( fp );
365 192 : if (pszLine == NULL)
366 : {
367 0 : VSIFCloseL( fp );
368 0 : return FALSE;
369 : }
370 192 : char chDelimiter = CSVDetectSeperator(pszLine);
371 192 : VSIRewindL( fp );
372 :
373 : /* GNIS specific */
374 192 : if (pszGeonamesGeomFieldPrefix != NULL &&
375 : strchr(pszLine, '|') != NULL)
376 0 : chDelimiter = '|';
377 :
378 192 : char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE );
379 :
380 192 : if( CSLCount(papszFields) < 2 )
381 : {
382 0 : VSIFCloseL( fp );
383 0 : CSLDestroy( papszFields );
384 0 : return FALSE;
385 : }
386 :
387 192 : VSIRewindL( fp );
388 192 : CSLDestroy( papszFields );
389 :
390 : /* -------------------------------------------------------------------- */
391 : /* Create a layer. */
392 : /* -------------------------------------------------------------------- */
393 192 : nLayers++;
394 : papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers,
395 192 : sizeof(void*) * nLayers);
396 :
397 192 : CPLString osLayerName = CPLGetBasename(pszFilename);
398 192 : if (pszNfdcRunwaysGeomField != NULL)
399 : {
400 0 : osLayerName += "_";
401 0 : osLayerName += pszNfdcRunwaysGeomField;
402 : }
403 192 : else if (pszGeonamesGeomFieldPrefix != NULL &&
404 : !EQUAL(pszGeonamesGeomFieldPrefix, ""))
405 : {
406 0 : osLayerName += "_";
407 0 : osLayerName += pszGeonamesGeomFieldPrefix;
408 : }
409 192 : if (EQUAL(pszFilename, "/vsistdin/"))
410 0 : osLayerName = "layer";
411 192 : papoLayers[nLayers-1] =
412 : new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
413 384 : chDelimiter, pszNfdcRunwaysGeomField, pszGeonamesGeomFieldPrefix );
414 :
415 192 : return TRUE;
416 : }
417 :
418 : /************************************************************************/
419 : /* CreateLayer() */
420 : /************************************************************************/
421 :
422 : OGRLayer *
423 26 : OGRCSVDataSource::CreateLayer( const char *pszLayerName,
424 : OGRSpatialReference *poSpatialRef,
425 : OGRwkbGeometryType eGType,
426 : char ** papszOptions )
427 :
428 : {
429 : /* -------------------------------------------------------------------- */
430 : /* Verify we are in update mode. */
431 : /* -------------------------------------------------------------------- */
432 26 : if (!bUpdate)
433 : {
434 : CPLError( CE_Failure, CPLE_NoWriteAccess,
435 : "Data source %s opened read-only.\n"
436 : "New layer %s cannot be created.\n",
437 0 : pszName, pszLayerName );
438 :
439 0 : return NULL;
440 : }
441 :
442 : /* -------------------------------------------------------------------- */
443 : /* Verify that the datasource is a directory. */
444 : /* -------------------------------------------------------------------- */
445 : VSIStatBufL sStatBuf;
446 :
447 26 : if( strncmp(pszName, "/vsizip/", 8) == 0)
448 : {
449 : /* Do nothing */
450 : }
451 26 : else if( !EQUAL(pszName, "/vsistdout/") &&
452 : (VSIStatL( pszName, &sStatBuf ) != 0
453 : || !VSI_ISDIR( sStatBuf.st_mode )) )
454 : {
455 : CPLError( CE_Failure, CPLE_AppDefined,
456 0 : "Attempt to create csv layer (file) against a non-directory datasource." );
457 0 : return NULL;
458 : }
459 :
460 : /* -------------------------------------------------------------------- */
461 : /* What filename would we use? */
462 : /* -------------------------------------------------------------------- */
463 26 : CPLString osFilename;
464 :
465 26 : if( osDefaultCSVName != "" )
466 : {
467 2 : osFilename = CPLFormFilename( pszName, osDefaultCSVName, NULL );
468 2 : osDefaultCSVName = "";
469 : }
470 : else
471 : {
472 24 : osFilename = CPLFormFilename( pszName, pszLayerName, "csv" );
473 : }
474 :
475 : /* -------------------------------------------------------------------- */
476 : /* Does this directory/file already exist? */
477 : /* -------------------------------------------------------------------- */
478 26 : if( VSIStatL( osFilename, &sStatBuf ) == 0 )
479 : {
480 : CPLError( CE_Failure, CPLE_AppDefined,
481 : "Attempt to create layer %s, but %s already exists.",
482 0 : pszLayerName, osFilename.c_str() );
483 0 : return NULL;
484 : }
485 :
486 : /* -------------------------------------------------------------------- */
487 : /* Create the empty file. */
488 : /* -------------------------------------------------------------------- */
489 :
490 26 : const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR");
491 26 : char chDelimiter = ',';
492 26 : if (pszDelimiter != NULL)
493 : {
494 2 : if (EQUAL(pszDelimiter, "COMMA"))
495 0 : chDelimiter = ',';
496 2 : else if (EQUAL(pszDelimiter, "SEMICOLON"))
497 2 : chDelimiter = ';';
498 0 : else if (EQUAL(pszDelimiter, "TAB"))
499 0 : chDelimiter = '\t';
500 : else
501 : {
502 : CPLError( CE_Warning, CPLE_AppDefined,
503 : "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON or TAB.",
504 0 : pszDelimiter );
505 : }
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Create a layer. */
510 : /* -------------------------------------------------------------------- */
511 26 : nLayers++;
512 : papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers,
513 26 : sizeof(void*) * nLayers);
514 :
515 26 : papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename,
516 52 : TRUE, TRUE, chDelimiter, NULL, NULL );
517 :
518 : /* -------------------------------------------------------------------- */
519 : /* Was a partiuclar CRLF order requested? */
520 : /* -------------------------------------------------------------------- */
521 52 : const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
522 : int bUseCRLF;
523 :
524 26 : if( pszCRLFFormat == NULL )
525 : {
526 : #ifdef WIN32
527 : bUseCRLF = TRUE;
528 : #else
529 24 : bUseCRLF = FALSE;
530 : #endif
531 : }
532 2 : else if( EQUAL(pszCRLFFormat,"CRLF") )
533 2 : bUseCRLF = TRUE;
534 0 : else if( EQUAL(pszCRLFFormat,"LF") )
535 0 : bUseCRLF = FALSE;
536 : else
537 : {
538 : CPLError( CE_Warning, CPLE_AppDefined,
539 : "LINEFORMAT=%s not understood, use one of CRLF or LF.",
540 0 : pszCRLFFormat );
541 : #ifdef WIN32
542 : bUseCRLF = TRUE;
543 : #else
544 0 : bUseCRLF = FALSE;
545 : #endif
546 : }
547 :
548 26 : papoLayers[nLayers-1]->SetCRLF( bUseCRLF );
549 :
550 : /* -------------------------------------------------------------------- */
551 : /* Should we write the geometry ? */
552 : /* -------------------------------------------------------------------- */
553 26 : const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
554 26 : if (pszGeometry != NULL)
555 : {
556 10 : if (EQUAL(pszGeometry, "AS_WKT"))
557 : {
558 4 : papoLayers[nLayers-1]->SetWriteGeometry(OGR_CSV_GEOM_AS_WKT);
559 : }
560 12 : else if (EQUAL(pszGeometry, "AS_XYZ") ||
561 : EQUAL(pszGeometry, "AS_XY") ||
562 : EQUAL(pszGeometry, "AS_YX"))
563 : {
564 12 : if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint)
565 : {
566 6 : papoLayers[nLayers-1]->SetWriteGeometry(EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
567 : EQUAL(pszGeometry, "AS_XY") ? OGR_CSV_GEOM_AS_XY :
568 12 : OGR_CSV_GEOM_AS_YX);
569 : }
570 : else
571 : {
572 : CPLError( CE_Warning, CPLE_AppDefined,
573 : "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.",
574 0 : OGRGeometryTypeToName(eGType) );
575 : }
576 : }
577 : else
578 : {
579 : CPLError( CE_Warning, CPLE_AppDefined,
580 : "Unsupported value %s for creation option GEOMETRY",
581 0 : pszGeometry );
582 : }
583 : }
584 :
585 : /* -------------------------------------------------------------------- */
586 : /* Should we create a CSVT file ? */
587 : /* -------------------------------------------------------------------- */
588 :
589 26 : const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT");
590 26 : if (pszCreateCSVT)
591 8 : papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT));
592 :
593 26 : return papoLayers[nLayers-1];
594 : }
595 :
596 : /************************************************************************/
597 : /* DeleteLayer() */
598 : /************************************************************************/
599 :
600 2 : OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
601 :
602 : {
603 : char *pszFilename;
604 : char *pszFilenameCSVT;
605 :
606 : /* -------------------------------------------------------------------- */
607 : /* Verify we are in update mode. */
608 : /* -------------------------------------------------------------------- */
609 2 : if( !bUpdate )
610 : {
611 : CPLError( CE_Failure, CPLE_NoWriteAccess,
612 : "Data source %s opened read-only.\n"
613 : "Layer %d cannot be deleted.\n",
614 0 : pszName, iLayer );
615 :
616 0 : return OGRERR_FAILURE;
617 : }
618 :
619 2 : if( iLayer < 0 || iLayer >= nLayers )
620 : {
621 : CPLError( CE_Failure, CPLE_AppDefined,
622 : "Layer %d not in legal range of 0 to %d.",
623 0 : iLayer, nLayers-1 );
624 0 : return OGRERR_FAILURE;
625 : }
626 :
627 : pszFilename =
628 2 : CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csv"));
629 : pszFilenameCSVT =
630 2 : CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csvt"));
631 :
632 2 : delete papoLayers[iLayer];
633 :
634 6 : while( iLayer < nLayers - 1 )
635 : {
636 2 : papoLayers[iLayer] = papoLayers[iLayer+1];
637 2 : iLayer++;
638 : }
639 :
640 2 : nLayers--;
641 :
642 2 : VSIUnlink( pszFilename );
643 2 : CPLFree( pszFilename );
644 2 : VSIUnlink( pszFilenameCSVT );
645 2 : CPLFree( pszFilenameCSVT );
646 :
647 2 : return OGRERR_NONE;
648 : }
|