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

📄 mitab_tabview.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    char *pszTableName = TABGetBasename(m_pszFname);
    if ( m_poRelation->Init(pszTableName,
                            m_papoTABFiles[0], m_papoTABFiles[1],
                            m_papszWhereClause[4], m_papszWhereClause[2],
                            m_papszFieldNames)  != 0 )
    {
        // An error should already have been reported
        CPLFree(pszTableName);
        Close();
        return -1;
    }
    CPLFree(pszTableName);

    return 0;
}


/**********************************************************************
 *                   TABView::OpenForWrite()
 *
 * Create a new TABView dataset
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int TABView::OpenForWrite(const char *pszFname)
{
    int nFnameLen = 0;
   
    m_eAccessMode = TABWrite;

    /*-----------------------------------------------------------------
     * Read main .TAB (text) file
     *----------------------------------------------------------------*/
    m_pszFname = CPLStrdup(pszFname);

#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(m_pszFname);
#endif

    /*-----------------------------------------------------------------
     * Extract the path component from the main .TAB filename
     *----------------------------------------------------------------*/
    char *pszPath = CPLStrdup(m_pszFname);
    nFnameLen = strlen(pszPath);
    for( ; nFnameLen > 0; nFnameLen--)
    {
        if (pszPath[nFnameLen-1] == '/' || 
            pszPath[nFnameLen-1] == '\\' )
        {
            break;
        }
        pszPath[nFnameLen-1] = '\0';
    }

    char *pszBasename = TABGetBasename(m_pszFname);

    /*-----------------------------------------------------------------
     * Create the 2 TAB files for the view.
     *
     * __TODO__ For now, we support only 2 files linked through a single
     *          field... not sure if anything else than that can be useful
     *          anyways.
     *----------------------------------------------------------------*/
    m_numTABFiles = 2;
    m_papszTABFnames = NULL;
    m_nMainTableIndex = 0;
    m_bRelFieldsCreated = FALSE;

    m_papoTABFiles = (TABFile**)CPLCalloc(m_numTABFiles, sizeof(TABFile*));

    for (int iFile=0; iFile < m_numTABFiles; iFile++)
    {
        m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames, "%s%s%d.tab", 
                                               pszPath, pszBasename, iFile+1);
#ifndef _WIN32
        TABAdjustFilenameExtension(m_papszTABFnames[iFile]);
#endif
        
        m_papoTABFiles[iFile] = new TABFile;
   
        if ( m_papoTABFiles[iFile]->Open(m_papszTABFnames[iFile], "wb") != 0)
        {
            // Open Failed... an error has already been reported, just return.
            CPLFree(pszPath);
            CPLFree(pszBasename);
            Close();
            return -1;
        }
    }

    /*-----------------------------------------------------------------
     * Create TABRelation... 
     *----------------------------------------------------------------*/
    m_poRelation = new TABRelation;
    
    if ( m_poRelation->Init(pszBasename,
                            m_papoTABFiles[0], m_papoTABFiles[1],
                            NULL, NULL, NULL)  != 0 )
    {
        // An error should already have been reported
        CPLFree(pszPath);
        CPLFree(pszBasename);
        Close();
        return -1;
    }

    CPLFree(pszPath);
    CPLFree(pszBasename);

    return 0;
}



/**********************************************************************
 *                   TABView::ParseTABFile()
 *
 * Scan the lines of the TAB file, and store any useful information into
 * class members.  The main piece of information being the sub-table
 * names, and the list of fields to include in the view that we will
 * use to build the OGRFeatureDefn for this file.
 *
 * It is assumed that the TAB header file is already loaded in m_papszTABFile
 *
 * This private method should be used only during the Open() call.
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int TABView::ParseTABFile(const char *pszDatasetPath, 
                          GBool bTestOpenNoError /*=FALSE*/)
{
    int         iLine, numLines;
    char        **papszTok=NULL;
    GBool       bInsideTableDef = FALSE;

    if (m_eAccessMode != TABRead)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
                 "ParseTABFile() can be used only with Read access.");
        return -1;
    }

    numLines = CSLCount(m_papszTABFile);

    for(iLine=0; iLine<numLines; iLine++)
    {
        /*-------------------------------------------------------------
         * Tokenize the next .TAB line, and check first keyword
         *------------------------------------------------------------*/
        CSLDestroy(papszTok);
        papszTok = CSLTokenizeStringComplex(m_papszTABFile[iLine], " \t(),;",
                                            TRUE, FALSE);
        if (CSLCount(papszTok) < 2)
            continue;   // All interesting lines have at least 2 tokens

        if (EQUAL(papszTok[0], "!version"))
        {
            m_pszVersion = CPLStrdup(papszTok[1]);
        }
        else if (EQUAL(papszTok[0], "!charset"))
        {
            CPLFree(m_pszCharset);
            m_pszCharset = CPLStrdup(papszTok[1]);
        }
        else if (EQUAL(papszTok[0], "open") &&
                 EQUAL(papszTok[1], "table") &&
                 CSLCount(papszTok) >= 3)
        {
            // Source table name may be either "filename" or "filename.tab"
            int nLen = strlen(papszTok[2]);
            if (nLen > 4 && EQUAL(papszTok[2]+nLen-4, ".tab"))
                papszTok[2][nLen-4] = '\0';

            m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames, 
                                               "%s%s.tab", 
                                               pszDatasetPath, papszTok[2]);
        }
        else if (EQUAL(papszTok[0], "create") &&
                 EQUAL(papszTok[1], "view") )
        {
            bInsideTableDef = TRUE;
        }
        else if (bInsideTableDef &&
                 (EQUAL(papszTok[0],"Select")))
        {
            /*---------------------------------------------------------
             * We found the list of table fields (comma-delimited list)
             *--------------------------------------------------------*/
            int iTok;
            for(iTok=1; papszTok[iTok] != NULL; iTok++)
                m_papszFieldNames = CSLAddString(m_papszFieldNames, 
                                                 papszTok[iTok]);

        }
        else if (bInsideTableDef &&
                 (EQUAL(papszTok[0],"where")))
        {
            /*---------------------------------------------------------
             * We found the where clause that relates the 2 tables
             * Something in the form:
             *   where table1.field1=table2.field2
             * The tokenized array will contain:
             *  {"where", "table1", "field1", "table2", "field2"}
             *--------------------------------------------------------*/
            m_papszWhereClause =CSLTokenizeStringComplex(m_papszTABFile[iLine],
                                                         " \t(),;=.",
                                                         TRUE, FALSE);

            /*---------------------------------------------------------
             * For now we are very limiting on the format of the WHERE
             * clause... we will be more permitting as we learn more about
             * what it can contain... (I don't want to implement a full SQL 
             * parser here!!!).  If you encountered this error,
             * (and are reading this!) please report the test dataset 
             * that produced the error and I'll see if we can support it.
             *--------------------------------------------------------*/
            if (CSLCount( m_papszWhereClause ) != 5)
            {
                if (!bTestOpenNoError)
                    CPLError(CE_Failure, CPLE_NotSupported,
                     "WHERE clause in %s is not in a supported format: \"%s\"",
                             m_pszFname, m_papszTABFile[iLine]);
                return -1;
            }
        }
        else
        {
            // Simply Ignore unrecognized lines
        }
    }

    CSLDestroy(papszTok);

    /*-----------------------------------------------------------------
     * The main table is the one from which we read the geometries, etc...
     * For now we assume it is always the first one in the list
     *----------------------------------------------------------------*/
    m_nMainTableIndex = 0;

    /*-----------------------------------------------------------------
     * Make sure all required class members are set
     *----------------------------------------------------------------*/
    m_numTABFiles = CSLCount(m_papszTABFnames);

    if (m_pszCharset == NULL)
        m_pszCharset = CPLStrdup("Neutral");
    if (m_pszVersion == NULL)
        m_pszVersion = CPLStrdup("100");

    if (CSLCount(m_papszFieldNames) == 0 )
    {
        if (!bTestOpenNoError)
            CPLError(CE_Failure, CPLE_NotSupported,
                     "%s: header contains no table field definition.  "
                     "This type of .TAB file cannot be read by this library.",
                     m_pszFname);
        return -1;
    }

    if (CSLCount(m_papszWhereClause) == 0 )
    {
        if (!bTestOpenNoError)
            CPLError(CE_Failure, CPLE_NotSupported,
                     "%s: WHERE clause not found or missing in header.  "
                     "This type of .TAB file cannot be read by this library.",
                     m_pszFname);
        return -1;
    }
    return 0;
}


/**********************************************************************
 *                   TABView::WriteTABFile()
 *
 * Generate the TAB header file.  This is usually done during the 
 * Close() call.
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int TABView::WriteTABFile()
{
    FILE *fp;

    CPLAssert(m_eAccessMode == TABWrite);
    CPLAssert(m_numTABFiles == 2);
    CPLAssert(GetLayerDefn());

    char *pszTable  = TABGetBasename(m_pszFname);
    char *pszTable1 = TABGetBasename(m_papszTABFnames[0]);
    char *pszTable2 = TABGetBasename(m_papszTABFnames[1]);

    if ( (fp = VSIFOpen(m_pszFname, "wt")) != NULL)
    {
        // Version is always 100, no matter what the sub-table's version is
        fprintf(fp, "!Table\n");
        fprintf(fp, "!Version 100\n");

        fprintf(fp, "Open Table \"%s\" Hide\n", pszTable1);
        fprintf(fp, "Open Table \"%s\" Hide\n", pszTable2);
        fprintf(fp, "\n");
        fprintf(fp, "Create View %s As\n", pszTable);
        fprintf(fp, "Select ");

        OGRFeatureDefn *poDefn = GetLayerDefn();
        for(int iField=0; iField<poDefn->GetFieldCount(); iField++)
        {
            OGRFieldDefn *poFieldDefn = poDefn->GetFieldDefn(iField);
            if (iField == 0)
                fprintf(fp, "%s", poFieldDefn->GetNameRef());
            else
                fprintf(fp, ",%s", poFieldDefn->GetNameRef());
        }
        fprintf(fp, "\n");

        fprintf(fp, "From %s, %s\n", pszTable2, pszTable1);
        fprintf(fp, "Where %s.%s=%s.%s\n", pszTable2, 
                                           m_poRelation->GetRelFieldName(),
                                           pszTable1, 
                                           m_poRelation->GetMainFieldName());


        VSIFClose(fp);
    }
    else
    {
        CPLError(CE_Failure, CPLE_FileIO,
                 "Failed to create file `%s'", m_pszFname);
        return -1;
    }

    CPLFree(pszTable);
    CPLFree(pszTable1);
    CPLFree(pszTable2);

    return 0;
}


/**********************************************************************
 *                   TABView::Close()
 *
 * Close current file, and release all memory used.
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int TABView::Close()
{
    // In write access, the main .TAB file has not been written yet.
    if (m_eAccessMode == TABWrite && m_poRelation)
        WriteTABFile();

    for(int i=0; m_papoTABFiles && i<m_numTABFiles; i++)
    {
        if (m_papoTABFiles[i])
            delete m_papoTABFiles[i];  // Automatically closes.
    }
    CPLFree(m_papoTABFiles);
    m_papoTABFiles = NULL;
    m_numTABFiles = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -