📄 tabdatfile.cpp
字号:
// In Native tables, we are guaranteed it is 1 byte with 0/1 value bValue = m_poRecordBlock->ReadByte(); } return bValue? "T":"F";}/********************************************************************** * TABDATFile::ReadDateField() * * Read the logical field value at the current position in the data * block. * * A date field is a 4 bytes binary value in which the first byte is * the day, followed by 1 byte for the month, and 2 bytes for the year. * * We return an 8 chars string in the format "YYYYMMDD" * * Note: nWidth is used only with TABTableDBF types. * * Returns a reference to an internal buffer that will be valid only until * the next field is read, or "" if the operation failed, in which case * CPLError() will have been called. **********************************************************************/const char *TABDATFile::ReadDateField(int nWidth){ int nDay, nMonth, nYear; static char szBuf[20]; // If current record has been deleted, then return an acceptable // default value. if (m_bCurRecordDeletedFlag) return ""; if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't read field value: file is not opened."); return ""; } // With .DBF files, there is nothing to do... the value should already // be stored in YYYYMMDD format according to DBF specs. if (m_eTableType == TABTableDBF) return ReadCharField(nWidth); nYear = m_poRecordBlock->ReadInt16(); nMonth = m_poRecordBlock->ReadByte(); nDay = m_poRecordBlock->ReadByte(); if (UGKGetLastErrorNo() != 0 || (nYear==0 && nMonth==0 && nDay==0)) return ""; sprintf(szBuf, "%4.4d%2.2d%2.2d", nYear, nMonth, nDay); return szBuf;}/********************************************************************** * TABDATFile::ReadDecimalField() * * Read the decimal field value at the current position in the data * block. * * A decimal field is a floating point value with a fixed number of digits * stored as a character string. * * nWidth is the field length, as defined in the .DAT header. * * We return the value as a binary double. * * CPLError() will have been called if something fails. **********************************************************************/double TABDATFile::ReadDecimalField(int nWidth){ const char *pszVal; // If current record has been deleted, then return an acceptable // default value. if (m_bCurRecordDeletedFlag) return 0.0; pszVal = ReadCharField(nWidth); return atof(pszVal);}/********************************************************************** * TABDATFile::WriteCharField() * * Write the character field value at the current position in the data * block. * * Use GetRecordBlock() to position the data block to the beginning of * a record before attempting to write values. * * nWidth is the field length, as defined in the .DAT header. * * Returns 0 on success, or -1 if the operation failed, in which case * CPLError() will have been called. **********************************************************************/int TABDATFile::WriteCharField(const char *pszStr, int nWidth, TABINDFile *poINDFile, int nIndexNo){ if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } if (nWidth < 1 || nWidth > 255) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Illegal width for a char field: %d", nWidth); return -1; } // // Write the buffer after making sure that we don't try to read // past the end of the source buffer. The rest of the field will // be padded with zeros if source string is shorter than specified // field width. // int nLen = strlen(pszStr); nLen = MIN(nLen, nWidth); if ((nLen>0 && m_poRecordBlock->WriteBytes(nLen, (UGKByte*)pszStr) != 0) || (nWidth-nLen > 0 && m_poRecordBlock->WriteZeros(nWidth-nLen)!=0) ) return -1; // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, pszStr); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return 0;}/********************************************************************** * TABDATFile::WriteIntegerField() * * Write the integer field value at the current position in the data * block. * * CPLError() will have been called if something fails. **********************************************************************/int TABDATFile::WriteIntegerField(UGKInt32 nValue, TABINDFile *poINDFile, int nIndexNo){ if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, nValue); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return m_poRecordBlock->WriteInt32(nValue);}/********************************************************************** * TABDATFile::WriteSmallIntField() * * Write the smallint field value at the current position in the data * block. * * CPLError() will have been called if something fails. **********************************************************************/int TABDATFile::WriteSmallIntField(UGKInt16 nValue, TABINDFile *poINDFile, int nIndexNo){ if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, nValue); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return m_poRecordBlock->WriteInt16(nValue);}/********************************************************************** * TABDATFile::WriteFloatField() * * Write the float field value at the current position in the data * block. * * CPLError() will have been called if something fails. **********************************************************************/int TABDATFile::WriteFloatField(double dValue, TABINDFile *poINDFile, int nIndexNo){ if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, dValue); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return m_poRecordBlock->WriteDouble(dValue);}/********************************************************************** * TABDATFile::WriteLogicalField() * * Write the logical field value at the current position in the data * block. * * The value written to the file is either 0 or 1, but this function * takes as input a string with "F" (false) or "T" (true) * * CPLError() will have been called if something fails. **********************************************************************/int TABDATFile::WriteLogicalField(const char *pszValue, TABINDFile *poINDFile, int nIndexNo){ UGKByte bValue; if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } if (EQUALN(pszValue, "T", 1)) bValue = 1; else bValue = 0; // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, (int)bValue); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return m_poRecordBlock->WriteByte(bValue);}/********************************************************************** * TABDATFile::WriteDateField() * * Write the date field value at the current position in the data * block. * * A date field is a 4 bytes binary value in which the first byte is * the day, followed by 1 byte for the month, and 2 bytes for the year. * * The expected input is a 10 chars string in the format "YYYY/MM/DD" * or "DD/MM/YYYY" or "YYYYMMDD" * * Returns 0 on success, or -1 if the operation failed, in which case * CPLError() will have been called. **********************************************************************/int TABDATFile::WriteDateField(const char *pszValue, TABINDFile *poINDFile, int nIndexNo){ int nDay, nMonth, nYear; char **papszTok = NULL; if (m_poRecordBlock == NULL) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Can't write field value: GetRecordBlock() has not been called."); return -1; } /*----------------------------------------------------------------- * Get rid of leading spaces. *----------------------------------------------------------------*/ while ( *pszValue == ' ' ) { pszValue++; } /*----------------------------------------------------------------- * Try to automagically detect date format, one of: * "YYYY/MM/DD", "DD/MM/YYYY", or "YYYYMMDD" *----------------------------------------------------------------*/ if (strlen(pszValue) == 8) { /*------------------------------------------------------------- * "YYYYMMDD" *------------------------------------------------------------*/ char szBuf[9]; strcpy(szBuf, pszValue); nDay = atoi(szBuf+6); szBuf[6] = '\0'; nMonth = atoi(szBuf+4); szBuf[4] = '\0'; nYear = atoi(szBuf); } else if (strlen(pszValue) == 10 && (papszTok = TokenizeStringComplex(pszValue, "/", FALSE, FALSE)) != NULL && CountOfList(papszTok) == 3 && (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) ) { /*------------------------------------------------------------- * Either "YYYY/MM/DD" or "DD/MM/YYYY" *------------------------------------------------------------*/ if (strlen(papszTok[0]) == 4) { nYear = atoi(papszTok[0]); nMonth = atoi(papszTok[1]); nDay = atoi(papszTok[2]); } else { nYear = atoi(papszTok[2]); nMonth = atoi(papszTok[1]); nDay = atoi(papszTok[0]); } } else if (strlen(pszValue) == 0) { nYear = nMonth = nDay = 0; } else { UGKError(ET_Failure, UGKErr_AppDefined, "Invalid date field value `%s'. Date field values must " "be in the format `YYYY/MM/DD', `MM/DD/YYYY' or `YYYYMMDD'", pszValue); FreeStrList(papszTok); return -1; } FreeStrList(papszTok); m_poRecordBlock->WriteInt16(nYear); m_poRecordBlock->WriteByte(nMonth); m_poRecordBlock->WriteByte(nDay); if (UGKGetLastErrorNo() != 0) return -1; // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, (nYear*0x10000 + nMonth * 0x100 + nDay)); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return 0;}/********************************************************************** * TABDATFile::WriteDecimalField() * * Write the decimal field value at the current position in the data * block. * * A decimal field is a floating point value with a fixed number of digits * stored as a character string. * * nWidth is the field length, as defined in the .DAT header. * * CPLError() will have been called if something fails. **********************************************************************/int TABDATFile::WriteDecimalField(double dValue, int nWidth, int nPrec, TABINDFile *poINDFile, int nIndexNo){ const char *pszVal; pszVal = UGKSPrintf("%*.*f", nWidth, nPrec, dValue); if ((int)strlen(pszVal) > nWidth) pszVal += strlen(pszVal) - nWidth; // Update Index if (poINDFile && nIndexNo > 0) { UGKByte *pKey = poINDFile->BuildKey(nIndexNo, dValue); if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0) return -1; } return m_poRecordBlock->WriteBytes(nWidth, (UGKByte*)pszVal);}/********************************************************************** * TABDATFile::Dump() * * Dump block contents... available only in DEBUG mode. **********************************************************************/void TABDATFile::Dump(FILE *fpOut /*=NULL*/){ if (fpOut == NULL) fpOut = stdout; fprintf(fpOut, "----- TABDATFile::Dump() -----\n"); if (m_fp == NULL) { fprintf(fpOut, "File is not opened.\n"); } else { fprintf(fpOut, "File is opened: %s\n", m_pszFname); fprintf(fpOut, "m_numFields = %d\n", m_numFields); fprintf(fpOut, "m_numRecords = %d\n", m_numRecords); } fflush(fpOut);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -