?? avc_e00write.c
字號:
/********************************************************************** * $Id: avc_e00write.c,v 1.20 2006/06/27 18:38:43 dmorissette Exp $ * * Name: avc_e00write.c * Project: Arc/Info vector coverage (AVC) E00->BIN conversion library * Language: ANSI C * Purpose: Functions to create a binary coverage from a stream of * ASCII E00 lines. * Author: Daniel Morissette, dmorissette@dmsolutions.ca * ********************************************************************** * Copyright (c) 1999-2001, Daniel Morissette * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ********************************************************************** * * $Log: avc_e00write.c,v $ * Revision 1.20 2006/06/27 18:38:43 dmorissette * Cleaned up E00 reading (bug 1497, patch from James F.) * * Revision 1.19 2006/06/14 16:31:28 daniel * Added support for AVCCoverPC2 type (bug 1491) * * Revision 1.18 2006/03/02 22:46:26 daniel * Accept empty subclass names for TX6/TX7 sections (bug 1261) * * Revision 1.17 2005/06/03 03:49:59 daniel * Update email address, website url, and copyright dates * * Revision 1.16 2002/08/27 15:46:15 daniel * Applied fix made in GDAL/OGR by 'aubin' (moved include ctype.h after avc.h) * * Revision 1.15 2002/04/16 21:19:10 daniel * Use VSIRmdir() * * Revision 1.14 2002/03/18 19:00:44 daniel * Use VSIMkdir() and not VSIMkDir() * * Revision 1.13 2002/02/18 21:16:33 warmerda * modified to use VSIMkDir * * Revision 1.12 2001/05/23 15:23:17 daniel * Remove trailing '/' in info directory path when creating the info dir. * * Revision 1.11 2000/09/26 20:21:04 daniel * Added AVCCoverPC write * * Revision 1.10 2000/09/22 19:45:21 daniel * Switch to MIT-style license * * Revision 1.9 2000/05/29 22:47:39 daniel * Made validation on new coverage name more flexible. * * Revision 1.8 2000/05/29 15:31:31 daniel * Added Japanese DBCS support * * Revision 1.7 2000/02/14 17:19:53 daniel * Accept '-' cahracter in new coverage name * * Revision 1.6 2000/01/10 02:57:44 daniel * Little changes to accomodate read support for "weird" coverages * * Revision 1.5 1999/12/24 07:18:34 daniel * Added PC Arc/Info coverages support * * Revision 1.4 1999/08/26 17:36:36 daniel * Avoid overwriting arc.dir on Windows... happened only when several * coverages are created by the same process on Windows. * * Revision 1.3 1999/08/23 18:23:35 daniel * Added AVCE00DeleteCoverage() * * Revision 1.2 1999/05/17 16:23:36 daniel * Added AVC_DEFAULT_PREC + more cover name validation in AVCE00WriteOpen(). * * Revision 1.1 1999/05/11 02:34:46 daniel * Initial revision * **********************************************************************/#include "cpl_vsi.h"#include "avc.h"#include <ctype.h> /* tolower() */static GBool _IsStringAlnum(const char *pszFname);/********************************************************************** * AVCE00WriteOpen() * * Open (create) an Arc/Info coverage, ready to be receive a stream * of ASCII E00 lines and convert that to the binary coverage format. * * For now, writing to or overwriting existing coverages is not supported * (and may quite well never be!)... you can only create new coverages. * * Important Note: The E00 source lines are assumed to be valid... the * library performs no validation on the consistency of what it is * given as input (i.e. topology, polygons consistency, etc.). * So the coverage that will be created will be only as good as the * E00 input that is used to generate it. * * pszCoverPath MUST be the name of the coverage directory, including * the path to it. * (contrary to AVCE00ReadOpen(), you cannot pass the name of one of * the files in the coverage directory). * The name of the coverage MUST be included in pszCoverPath... this * means that passing "." is invalid. * * eNewCoverType is the type of coverage to create. * Either AVCCoverV7 (Arc/Info V7 (Unix) coverage) * or AVCCoverPC (PC Arc/Info coverage) * * nPrecision should always be AVC_DEFAULT_PREC to automagically detect the * source coverage's precision and use that same precision * for the new coverage. * * This parameter has been included to allow adding the * possibility to eventually create coverages with a precision * different from the source E00. * Given the way the lib is built, it could be possible to * also pass AVC_SINGLE_PREC or AVC_DOUBLE_PREC to explicitly * request the creation of a coverage with that precision, * but the library does not (not yet!) properly convert the * TABLE attributes' precision, and the resulting coverage may * be invalid in some cases. * This improvement is on the ToDo list! * * Returns a new AVCE00WritePtr handle or NULL if the coverage could * not be created or if a coverage with that name already exists. * * The handle will eventually have to be released with AVCE00ReadClose(). **********************************************************************/AVCE00WritePtr AVCE00WriteOpen(const char *pszCoverPath, AVCCoverType eNewCoverType, int nPrecision ){ AVCE00WritePtr psInfo; int i, nLen; VSIStatBuf sStatBuf; CPLErrorReset(); /*----------------------------------------------------------------- * Create pszCoverPath directory. *----------------------------------------------------------------*/ if (pszCoverPath == NULL || strlen(pszCoverPath) == 0) { CPLError(CE_Failure, CPLE_AssertionFailed, "Invalid (empty) coverage directory name."); return NULL; } else if ( VSIStat(pszCoverPath, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode) ) { /*------------------------------------------------------------- * Directory already exists... make sure it is empty * otherwise we can't use it as a coverage directory. *------------------------------------------------------------*/ char **papszFiles; papszFiles = CPLReadDir(pszCoverPath); for(i=0; papszFiles && papszFiles[i]; i++) { if (!EQUAL(".", papszFiles[i]) && !EQUAL("..", papszFiles[i])) { CPLError(CE_Failure, CPLE_OpenFailed, "Cannot create coverage %s: directory already exists " "and is not empty.", pszCoverPath); CSLDestroy(papszFiles); papszFiles = NULL; return NULL; } } CSLDestroy(papszFiles); papszFiles = NULL; } else { /*------------------------------------------------------------- * Create new pszCoverPath directory. * This will fail if a file with the same name already exists. *------------------------------------------------------------*/ if( VSIMkdir(pszCoverPath, 0777) != 0 ) { CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create coverage directory: %s.", pszCoverPath); return NULL; } } /*----------------------------------------------------------------- * Alloc the AVCE00WritePtr handle *----------------------------------------------------------------*/ psInfo = (AVCE00WritePtr)CPLCalloc(1, sizeof(struct AVCE00WriteInfo_t)); /*----------------------------------------------------------------- * Validate and store coverage type *----------------------------------------------------------------*/ if (eNewCoverType == AVCCoverV7 || eNewCoverType == AVCCoverPC) psInfo->eCoverType = eNewCoverType; else { CPLError(CE_Failure, CPLE_NotSupported, "Requested coverage type cannot be created. Please use " "the AVCCoverV7 or AVCCoverPC coverage type."); CPLFree(psInfo); return NULL; } /*----------------------------------------------------------------- * Requested precision for the new coverage... for now only * AVC_DEFAULT_PREC is supported. When the first section is * read, then this section's precision will be used for the whole * coverage. (This is done inside AVCE00WriteNextLine()) *----------------------------------------------------------------*/ if (psInfo->eCoverType == AVCCoverPC) psInfo->nPrecision = AVC_SINGLE_PREC; /* PC Cover always single prec.*/ else if (nPrecision == AVC_DEFAULT_PREC) psInfo->nPrecision = nPrecision; else { CPLError(CE_Failure, CPLE_IllegalArg, "Coverages can only be created using AVC_DEFAULT_PREC. " "Please see the documentation for AVCE00WriteOpen()."); CPLFree(psInfo); return NULL; } /*----------------------------------------------------------------- * Make sure coverage directory name is terminated with a '/' (or '\\') *----------------------------------------------------------------*/ nLen = strlen(pszCoverPath); if (pszCoverPath[nLen-1] == '/' || pszCoverPath[nLen-1] == '\\') psInfo->pszCoverPath = CPLStrdup(pszCoverPath); else {#ifdef WIN32 psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s\\",pszCoverPath));#else psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s/",pszCoverPath));#endif } /*----------------------------------------------------------------- * Extract the coverage name from the coverage path. Note that * for this the coverage path must be in the form: * "dir1/dir2/dir3/covername/" ... if it is not the case, then * we would have to use getcwd() to find the current directory name... * but for now we'll just produce an error if this happens. *----------------------------------------------------------------*/ nLen = 0; for( i = strlen(psInfo->pszCoverPath)-1; i > 0 && psInfo->pszCoverPath[i-1] != '/' && psInfo->pszCoverPath[i-1] != '\\'&& psInfo->pszCoverPath[i-1] != ':'; i-- ) { nLen++; } if (nLen > 0) { psInfo->pszCoverName = CPLStrdup(psInfo->pszCoverPath+i); psInfo->pszCoverName[nLen] = '\0'; } else { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid coverage path (%s): " "coverage name must be included in path.", pszCoverPath); CPLFree(psInfo->pszCoverPath); CPLFree(psInfo); return NULL; } if (strlen(psInfo->pszCoverName) > 13 || !_IsStringAlnum(psInfo->pszCoverName) ) { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid coverage name (%s): " "coverage name must be 13 chars or less and contain only " "alphanumerical characters, '-' or '_'.", psInfo->pszCoverName); CPLFree(psInfo->pszCoverPath); CPLFree(psInfo->pszCoverName); CPLFree(psInfo); return NULL; } if (psInfo->eCoverType == AVCCoverPC || psInfo->eCoverType == AVCCoverPC2) { /*------------------------------------------------------------- * No 'info' directory is required for PC coverages *------------------------------------------------------------*/ psInfo->pszInfoPath = NULL; } else { /*------------------------------------------------------------- * Lazy way to build the INFO path: simply add "../info/"... * this could probably be improved! *------------------------------------------------------------*/ psInfo->pszInfoPath = (char*)CPLMalloc((strlen(psInfo->pszCoverPath)+9) *sizeof(char));#ifdef WIN32# define AVC_INFOPATH "..\\info\\"#else# define AVC_INFOPATH "../info/"#endif sprintf(psInfo->pszInfoPath, "%s%s", psInfo->pszCoverPath, AVC_INFOPATH); /*------------------------------------------------------------- * Check if the info directory exists and contains the "arc.dir" * if the info dir does not exist, then make sure we can create * the arc.dir file (i.e. try to create an empty one) * * Note: On Windows, this VSIStat() call seems to sometimes fail even
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -