⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mitab_miffile.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/**********************************************************************
 * $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 + -