📄 mitab_tabview.cpp
字号:
* 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")) { 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; /*----------------------------------------------------------------- * __TODO__ OK, MapInfo does not like to see a .map and .id file * attached to the second table, even if they're empty. * We'll use a little hack to delete them now, but eventually we * should avoid creating them at all. *----------------------------------------------------------------*/ if (m_eAccessMode == TABWrite && m_pszFname) { m_pszFname[strlen(m_pszFname)-4] = '\0'; char *pszFile = CPLStrdup(CPLSPrintf("%s2.map", m_pszFname)); TABAdjustFilenameExtension(pszFile); VSIUnlink(pszFile); sprintf(pszFile, "%s2.id", m_pszFname); TABAdjustFilenameExtension(pszFile); VSIUnlink(pszFile); CPLFree(pszFile); } // End of hack! CPLFree(m_pszFname); m_pszFname = NULL; CSLDestroy(m_papszTABFile); m_papszTABFile = NULL; CPLFree(m_pszVersion); m_pszVersion = NULL; CPLFree(m_pszCharset); m_pszCharset = NULL; CSLDestroy(m_papszTABFnames); m_papszTABFnames = NULL; CSLDestroy(m_papszFieldNames); m_papszFieldNames = NULL; CSLDestroy(m_papszWhereClause); m_papszWhereClause = NULL; m_nMainTableIndex = -1; if (m_poRelation)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -