📄 mitab_miffile.cpp
字号:
/**********************************************************************
* $Id: mitab_miffile.cpp,v 1.46 2008/02/01 20:30:59 dmorissette Exp $
*
* Name: mitab_miffile.cpp
* Project: MapInfo TAB Read/Write library
* Language: C++
* Purpose: Implementation of the MIDFile class.
* To be used by external programs to handle reading/writing of
* features from/to MID/MIF datasets.
* Author: Stephane Villeneuve, stephane.v@videotron.ca
*
**********************************************************************
* Copyright (c) 1999-2003, Stephane Villeneuve
*
* 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: mitab_miffile.cpp,v $
* Revision 1.46 2008/02/01 20:30:59 dmorissette
* Use %.15g instead of %.16g as number precision in .MIF output
*
* Revision 1.45 2008/01/29 21:56:39 dmorissette
* Update dataset version properly for Date/Time/DateTime field types (#1754)
*
* Revision 1.44 2008/01/29 20:46:32 dmorissette
* Added support for v9 Time and DateTime fields (byg 1754)
*
* Revision 1.43 2007/09/14 15:35:21 dmorissette
* Fixed problem with MIF parser being confused by special attribute
* names (bug 1795)
*
* Revision 1.42 2007/06/12 13:52:37 dmorissette
* Added IMapInfoFile::SetCharset() method (bug 1734)
*
* Revision 1.41 2005/10/13 20:12:03 fwarmerdam
* layers with just regions can't be set as type wkbPolygon because they may
* have multipolygons (bug GDAL:958)
* http://bugzilla.remotesensing.org/show_bug.cgi?id=958
*
* Revision 1.40 2005/10/12 14:03:02 fwarmerdam
* Fixed problem with white space parsing in mitab_miffile.cpp (bug GDAL:954)
*
* Revision 1.39 2005/10/04 19:36:10 dmorissette
* Added support for reading collections from MIF files (bug 1126)
*
* Revision 1.38 2004/02/27 21:04:14 fwarmerdam
* dont write MIF header if file is readonly - gdal bugzilla 509
*
* Revision 1.37 2003/12/19 07:54:50 fwarmerdam
* write mif header on close if not already written out
*
* Revision 1.36 2003/08/13 02:49:02 dmorissette
* Use tab as default delimiter if not explicitly specified (Anthony D, bug 37)
*
* Revision 1.35 2003/01/30 22:42:39 daniel
* Fixed crash in ParseMIFHeader() when .mif doesn't contain a DATA line
*
* Revision 1.34 2002/09/23 12:53:29 warmerda
* fix memory leak of m_pszIndex
*
* Revision 1.33 2002/05/08 15:10:48 julien
* Implement MIFFile::SetMIFCoordSys in mitab_capi.cpp (Bug 984)
*
* Revision 1.32 2002/04/26 14:16:49 julien
* Finishing the implementation of Multipoint (support for MIF)
*
* Revision 1.31 2001/09/19 21:39:15 warmerda
* get extents efficiently
*
* Revision 1.30 2001/09/19 14:31:22 warmerda
* added m_nPreloadedId to keep track of preloaded line
*
* Revision 1.29 2001/09/14 19:14:43 warmerda
* added attribute query support
*
* Revision 1.28 2001/08/10 17:49:01 warmerda
* fixed a few memory leaks
*
* Revision 1.27 2001/03/15 03:57:51 daniel
* Added implementation for new OGRLayer::GetExtent(), returning data MBR.
*
* Revision 1.26 2001/03/09 04:14:19 daniel
* Fixed problem creating new files with mixed case extensions (e.g. ".Tab")
*
* Revision 1.25 2001/03/09 03:51:48 daniel
* Fixed writing MIF header: missing break; for decimal fields
*
* Revision 1.24 2001/02/27 19:59:05 daniel
* Enabled spatial filter in IMapInfoFile::GetNextFeature(), and avoid
* unnecessary feature cloning in GetNextFeature() and GetFeature()
*
* Revision 1.23 2001/01/23 21:23:42 daniel
* Added projection bounds lookup table, called from TABFile::SetProjInfo()
*
* Revision 1.22 2001/01/22 16:03:58 warmerda
* expanded tabs
*
* Revision 1.21 2000/12/15 05:38:38 daniel
* Produce Warning instead of an error when nWidth>254 in AddFieldNative()
*
* Revision 1.20 2000/11/14 06:15:37 daniel
* Handle '\t' as spaces in parsing, and fixed GotoFeature() to avoid calling
* ResetReading() when reading forward.
*
* Revision 1.19 2000/07/04 01:50:40 warmerda
* Removed unprotected debugging printf.
*
* Revision 1.18 2000/06/28 00:32:04 warmerda
* Make GetFeatureCountByType() actually work if bForce is TRUE
* Collect detailed (by feature type) feature counts in PreParse().
*
* Revision 1.17 2000/04/27 15:46:25 daniel
* Make SetFeatureDefn() use AddFieldNative(), scan field names for invalid
* chars, and map field width=0 (variable length in OGR) to valid defaults
*
* Revision 1.16 2000/03/27 03:37:59 daniel
* Handle bounds in CoordSys for read and write, + handle point SYMBOL line as
* optional + fixed reading of bounds in PreParseFile()
*
* Revision 1.15 2000/02/28 17:05:06 daniel
* Added support for index and unique directives for read and write
*
* Revision 1.14 2000/01/28 07:32:25 daniel
* Validate char field width (must be <= 254 chars)
*
* Revision 1.13 2000/01/24 19:51:33 warmerda
* AddFieldNative should not fail for read-only datasets
*
* Revision 1.12 2000/01/18 23:13:41 daniel
* Implemented AddFieldNative()
*
* ...
*
* Revision 1.1 1999/11/08 04:16:07 stephane
* First Revision
*
**********************************************************************/
#include "mitab.h"
#include "mitab_utils.h"
#include <ctype.h>
/*=====================================================================
* class MIFFile
*====================================================================*/
/**********************************************************************
* MIFFile::MIFFile()
*
* Constructor.
**********************************************************************/
MIFFile::MIFFile()
{
m_pszFname = NULL;
m_nVersion = 300;
// Tab is default delimiter in MIF spec if not explicitly specified. Use
// that by default for read mode. In write mode, we will use "," as
// delimiter since it's more common than tab (we do this in Open())
m_pszDelimiter = CPLStrdup("\t");
m_pszUnique = NULL;
m_pszIndex = NULL;
m_pszCoordSys = NULL;
m_paeFieldType = NULL;
m_pabFieldIndexed = NULL;
m_pabFieldUnique = NULL;
m_dfXMultiplier = 1.0;
m_dfYMultiplier = 1.0;
m_dfXDisplacement = 0.0;
m_dfYDisplacement = 0.0;
m_poMIDFile = NULL;
m_poMIFFile = NULL;
m_nPreloadedId = 0;
m_poDefn = NULL;
m_poSpatialRef = NULL;
m_nCurFeatureId = 0;
m_nFeatureCount = 0;
m_nWriteFeatureId = -1;
m_poCurFeature = NULL;
m_bPreParsed = FALSE;
m_nAttribut = 0;
m_bHeaderWrote = FALSE;
m_nPoints = m_nLines = m_nRegions = m_nTexts = 0;
m_bExtentsSet = FALSE;
}
/**********************************************************************
* MIFFile::~MIFFile()
*
* Destructor.
**********************************************************************/
MIFFile::~MIFFile()
{
Close();
}
/**********************************************************************
* MIFFile::Open()
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int MIFFile::Open(const char *pszFname, const char *pszAccess,
GBool bTestOpenNoError /*=FALSE*/ )
{
char *pszTmpFname = NULL;
int nFnameLen = 0;
CPLErrorReset();
if (m_poMIDFile)
{
CPLError(CE_Failure, CPLE_FileIO,
"Open() failed: object already contains an open file");
return -1;
}
/*-----------------------------------------------------------------
* Validate access mode
*----------------------------------------------------------------*/
if (EQUALN(pszAccess, "r", 1))
{
m_eAccessMode = TABRead;
pszAccess = "rt";
}
else if (EQUALN(pszAccess, "w", 1))
{
m_eAccessMode = TABWrite;
pszAccess = "wt";
// In write mode, use "," as delimiter since it's more common than tab
CPLFree(m_pszDelimiter);
m_pszDelimiter = CPLStrdup(",");
}
else
{
if (!bTestOpenNoError)
CPLError(CE_Failure, CPLE_FileIO,
"Open() failed: access mode \"%s\" not supported", pszAccess);
else
CPLErrorReset();
return -1;
}
/*-----------------------------------------------------------------
* Make sure filename has a .MIF or .MID extension...
*----------------------------------------------------------------*/
m_pszFname = CPLStrdup(pszFname);
nFnameLen = strlen(m_pszFname);
if (nFnameLen > 4 && (strcmp(m_pszFname+nFnameLen-4, ".MID")==0 ||
strcmp(m_pszFname+nFnameLen-4, ".MIF")==0 ) )
strcpy(m_pszFname+nFnameLen-4, ".MIF");
else if (nFnameLen > 4 && (EQUAL(m_pszFname+nFnameLen-4, ".mid") ||
EQUAL(m_pszFname+nFnameLen-4, ".mif") ) )
strcpy(m_pszFname+nFnameLen-4, ".mif");
else
{
if (!bTestOpenNoError)
CPLError(CE_Failure, CPLE_FileIO,
"Open() failed for %s: invalid filename extension",
m_pszFname);
else
CPLErrorReset();
CPLFree(m_pszFname);
return -1;
}
pszTmpFname = CPLStrdup(m_pszFname);
/*-----------------------------------------------------------------
* Open .MIF file
*----------------------------------------------------------------*/
#ifndef _WIN32
/*-----------------------------------------------------------------
* On Unix, make sure extension uses the right cases
* We do it even for write access because if a file with the same
* extension already exists we want to overwrite it.
*----------------------------------------------------------------*/
TABAdjustFilenameExtension(pszTmpFname);
#endif
m_poMIFFile = new MIDDATAFile;
if (m_poMIFFile->Open(pszTmpFname, pszAccess) != 0)
{
if (!bTestOpenNoError)
CPLError(CE_Failure, CPLE_NotSupported,
"Unable to open %s.", pszTmpFname);
else
CPLErrorReset();
CPLFree(pszTmpFname);
Close();
return -1;
}
/*-----------------------------------------------------------------
* Open .MID file
*----------------------------------------------------------------*/
if (nFnameLen > 4 && strcmp(pszTmpFname+nFnameLen-4, ".MIF")==0)
strcpy(pszTmpFname+nFnameLen-4, ".MID");
else
strcpy(pszTmpFname+nFnameLen-4, ".mid");
#ifndef _WIN32
TABAdjustFilenameExtension(pszTmpFname);
#endif
m_poMIDFile = new MIDDATAFile;
if (m_poMIDFile->Open(pszTmpFname, pszAccess) !=0)
{
if (!bTestOpenNoError)
CPLError(CE_Failure, CPLE_NotSupported,
"Unable to open %s.", pszTmpFname);
else
CPLErrorReset();
CPLFree(pszTmpFname);
Close();
return -1;
}
CPLFree(pszTmpFname);
pszTmpFname = NULL;
/*-----------------------------------------------------------------
* Read MIF File Header
*----------------------------------------------------------------*/
if (m_eAccessMode == TABRead && ParseMIFHeader() != 0)
{
Close();
if (!bTestOpenNoError)
CPLError(CE_Failure, CPLE_NotSupported,
"Failed parsing header in %s.", m_pszFname);
else
CPLErrorReset();
return -1;
}
/*-----------------------------------------------------------------
* In write access, set some defaults
*----------------------------------------------------------------*/
if (m_eAccessMode == TABWrite)
{
m_nVersion = 300;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -