?? avc_e00read.c
字號:
/********************************************************************** * $Id: avc_e00read.c,v 1.21 2006/06/27 18:38:43 dmorissette Exp $ * * Name: avc_e00read.c * Project: Arc/Info vector coverage (AVC) BIN->E00 conversion library * Language: ANSI C * Purpose: Functions to open a binary coverage and read it as if it * was an ASCII E00 file. This file is the main entry point * for the library. * Author: Daniel Morissette, dmorissette@dmsolutions.ca * ********************************************************************** * Copyright (c) 1999-2005, 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_e00read.c,v $ * Revision 1.21 2006/06/27 18:38:43 dmorissette * Cleaned up E00 reading (bug 1497, patch from James F.) * * Revision 1.20 2006/06/27 18:06:34 dmorissette * Applied patch for EOP processing from James F. (bug 1497) * * Revision 1.19 2006/06/16 11:48:11 daniel * New functions to read E00 files directly as opposed to translating to * binary coverage. Used in the implementation of E00 read support in OGR. * Contributed by James E. Flemer. (bug 1497) * * Revision 1.18 2006/06/14 16:31:28 daniel * Added support for AVCCoverPC2 type (bug 1491) * * Revision 1.17 2005/06/03 03:49:58 daniel * Update email address, website url, and copyright dates * * Revision 1.16 2004/07/14 18:49:50 daniel * Fixed leak when trying to open something that's not a coverage (bug513) * * Revision 1.15 2002/08/27 15:46:15 daniel * Applied fix made in GDAL/OGR by 'aubin' (moved include ctype.h after avc.h) * * Revision 1.14 2000/09/22 19:45:21 daniel * Switch to MIT-style license * * Revision 1.13 2000/05/29 15:31:31 daniel * Added Japanese DBCS support * * Revision 1.12 2000/02/14 17:21:01 daniel * Made more robust for corrupted or invalid files in cover directory * * Revision 1.11 2000/02/02 04:26:04 daniel * Support reading TX6/TX7/RXP/RPL files in weird coverages * * Revision 1.10 2000/01/10 02:56:30 daniel * Added read support for "weird" coverages * * Revision 1.9 2000/01/07 07:12:49 daniel * Added support for reading PC Coverage TXT files * * Revision 1.8 1999/12/24 07:41:08 daniel * Check fname length before testing for extension in AVCE00ReadFindCoverType() * * Revision 1.7 1999/12/24 07:18:34 daniel * Added PC Arc/Info coverages support * * Revision 1.6 1999/08/26 17:22:18 daniel * Use VSIFopen() instead of fopen() directly * * Revision 1.5 1999/08/23 18:21:41 daniel * New syntax for AVCBinReadListTables() * * Revision 1.4 1999/05/11 02:10:01 daniel * Free psInfo struct inside AVCE00ReadClose() * * Revision 1.3 1999/04/06 19:43:26 daniel * Added E00 coverage path in EXP 0 header line * * Revision 1.2 1999/02/25 04:19:01 daniel * Added TXT, TX6/TX7, RXP and RPL support + other minor changes * * Revision 1.1 1999/01/29 16:28:52 daniel * Initial revision * **********************************************************************/#ifdef WIN32# include <direct.h> /* getcwd() */#endif#include "avc.h"#include <ctype.h> /* toupper() */static void _AVCE00ReadScanE00(AVCE00ReadE00Ptr psRead);static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo, char **papszCoverDir);static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir);/********************************************************************** * AVCE00ReadOpen() * * Open a Arc/Info coverage to read it as if it was an E00 file. * * You can either pass the name of the coverage directory, or the path * to one of the files in the coverage directory. The name of the * coverage MUST be included in pszCoverPath... this means that * passing "." is invalid. * The following are all valid values for pszCoverPath: * /home/data/country * /home/data/country/ * /home/data/country/arc.adf * (Of course you should replace the '/' with '\\' on DOS systems!) * * Returns a new AVCE00ReadPtr handle or NULL if the coverage could * not be opened or if it does not appear to be a valid Arc/Info coverage. * * The handle will eventually have to be released with AVCE00ReadClose(). **********************************************************************/AVCE00ReadPtr AVCE00ReadOpen(const char *pszCoverPath){ AVCE00ReadPtr psInfo; int i, nLen, nCoverPrecision; VSIStatBuf sStatBuf; char **papszCoverDir = NULL; CPLErrorReset(); /*----------------------------------------------------------------- * pszCoverPath must be either a valid directory name or a valid * file name. *----------------------------------------------------------------*/ if (pszCoverPath == NULL || strlen(pszCoverPath) == 0 || VSIStat(pszCoverPath, &sStatBuf) == -1) { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid coverage path: %s.", pszCoverPath?pszCoverPath:"(NULL)"); return NULL; } /*----------------------------------------------------------------- * Alloc the AVCE00ReadPtr handle *----------------------------------------------------------------*/ psInfo = (AVCE00ReadPtr)CPLCalloc(1, sizeof(struct AVCE00ReadInfo_t)); /*----------------------------------------------------------------- * 2 possibilities about the value passed in pszCoverPath: * - It can be the directory name of the coverage * - or it can be the path to one of the files in the coverage * * If the name passed in pszCoverPath is not a directory, then we * need to strip the last part of the filename to keep only the * path, terminated by a '/' (or a '\\'). *----------------------------------------------------------------*/ if (VSI_ISDIR(sStatBuf.st_mode)) { /*------------------------------------------------------------- * OK, we have a valid directory name... make sure it 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 } } else { /*------------------------------------------------------------- * We are dealing with a filename. * Extract the coverage path component and store it. * The coverage path will remain terminated by a '/' or '\\' char. *------------------------------------------------------------*/ psInfo->pszCoverPath = CPLStrdup(pszCoverPath); for( i = strlen(psInfo->pszCoverPath)-1; i > 0 && psInfo->pszCoverPath[i] != '/' && psInfo->pszCoverPath[i] != '\\'; i-- ) {} psInfo->pszCoverPath[i+1] = '\0'; } /*----------------------------------------------------------------- * 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; } /*----------------------------------------------------------------- * Read the coverage directory listing and try to establish the cover type *----------------------------------------------------------------*/ papszCoverDir = CPLReadDir(psInfo->pszCoverPath); psInfo->eCoverType = _AVCE00ReadFindCoverType(papszCoverDir); if (psInfo->eCoverType == AVCCoverTypeUnknown ) { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid coverage (%s): directory does not appear to " "contain any supported vector coverage file.", pszCoverPath); CPLFree(psInfo->pszCoverName); CPLFree(psInfo->pszCoverPath); CPLFree(psInfo->pszInfoPath); CPLFree(psInfo); CSLDestroy(papszCoverDir); return NULL; } /*----------------------------------------------------------------- * INFO path: PC Coverages have all files in the same dir, and unix * covers have the INFO files in ../info *----------------------------------------------------------------*/ if (psInfo->eCoverType == AVCCoverPC || psInfo->eCoverType == AVCCoverPC2) { psInfo->pszInfoPath = CPLStrdup(psInfo->pszCoverPath); } 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); AVCAdjustCaseSensitiveFilename(psInfo->pszInfoPath); } /*----------------------------------------------------------------- * For Unix coverages, check that the info directory exists and * contains the "arc.dir". In AVCCoverWeird, the arc.dir is * called "../INFO/ARCDR9". * PC Coverages have their info tables in the same direcotry as * the coverage files. *----------------------------------------------------------------*/ if ((psInfo->eCoverType == AVCCoverV7 && ! AVCFileExists(psInfo->pszInfoPath, "arc.dir") ) || (psInfo->eCoverType == AVCCoverWeird && ! AVCFileExists(psInfo->pszInfoPath, "arcdr9") ) ) { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid coverage (%s): 'info' directory not found or invalid.", pszCoverPath); CPLFree(psInfo->pszCoverName); CPLFree(psInfo->pszCoverPath); CPLFree(psInfo->pszInfoPath); CPLFree(psInfo); CSLDestroy(papszCoverDir); return NULL; } /*----------------------------------------------------------------- * Make sure there was no error until now before we build squeleton. *----------------------------------------------------------------*/ if (CPLGetLastErrorNo() != 0) { CPLFree(psInfo->pszCoverName); CPLFree(psInfo->pszCoverPath); CPLFree(psInfo->pszInfoPath); CPLFree(psInfo); CSLDestroy(papszCoverDir); return NULL; } /*----------------------------------------------------------------- * Build the E00 file squeleton and be ready to return a E00 header... * We'll also read the coverage precision by the same way.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -