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