diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2022-12-07 13:17:14 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2022-12-07 13:17:14 +0100 |
commit | 4875a3dd9b183dcd2256e2abfc4ccf7484c233b4 (patch) | |
tree | 0abbea881ded030851014ffdd60fbf71fead8f65 /xbase64/xbdbf.cpp | |
parent | daf17154bf13139d9375f48525d19d6aaba08155 (diff) |
New upstream version 4.0.2upstream/4.0.2
Diffstat (limited to 'xbase64/xbdbf.cpp')
-rwxr-xr-x | xbase64/xbdbf.cpp | 2671 |
1 files changed, 0 insertions, 2671 deletions
diff --git a/xbase64/xbdbf.cpp b/xbase64/xbdbf.cpp deleted file mode 100755 index d3790cb..0000000 --- a/xbase64/xbdbf.cpp +++ /dev/null @@ -1,2671 +0,0 @@ -/* xbdbf.cpp - - Xbase64 project source code - - This file contains the basic Xbase routines for reading and writing - Xbase .DBF files. - - Copyright (C) 1997,2003 Gary A Kunkel - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - Contact: - - Email: - - xdb-devel@lists.sourceforge.net - xdb-users@lists.sourceforge.net - - - Regular Mail: - - XBase Support - 149C South Main St - Keller Texas, 76248 - USA - -*/ - -#ifdef __GNU LesserG__ - #pragma implementation "xbdbf.h" -#endif - -#ifdef __WIN32__ -#include <xbase64/xbwincfg.h> -#else -#include <xbase64/xbconfig.h> -#endif - -#include <xbase64/xbase64.h> - -#ifdef HAVE_IO_H -#include <io.h> -#endif -#include <errno.h> - -/*! \file xbdbf.cpp -*/ - -/************************************************************************/ -//! Constructor -/*! - \param x pointer to the global xbXbase class -*/ -xbDbf::xbDbf( xbXBase * x ) -{ - xbase = x; - InitVars(); -} -/************************************************************************/ -//! Destructor -/*! -*/ -xbDbf::~xbDbf() -{ - CloseDatabase(true); -} -/************************************************************************/ -//! Initialize private data members. -/*! - Internal use only. -*/ -void xbDbf::InitVars() -{ - SetFileName(NULL); - NoOfFields = 0; - DbfStatus = XB_CLOSED; - fp = NULL; - CurRec = 0L; - SchemaPtr = NULL; - RecBuf = NULL; - RecBuf2 = NULL; - Version = 0x00; - UpdateYY = 0x00; - UpdateMM = 0x00; - UpdateDD = 0x00; - NoOfRecs = 0L; - HeaderLen = 0x00; - RecordLen = 0x00; - NdxList = NULL; - FreeIxList = NULL; - XFV = 3; /* Xbase file version */ - -#ifdef XB_LOCKING_ON - xblfh = NULL; /* lock file for XB_XBASE_LOCK_MODE */ - LockMode = xbase->GetLockMode(); - TableLockCnt = 0; - IndexLockCnt = 0; -#ifdef XB_MEMO_FIELDS - MemoLockCnt = 0; -#endif - - AutoLock = 1; - CurLockType = -1; - CurLockCount = 0; - CurLockedRecNo = 0L; - CurRecLockType = -1; - CurRecLockCount = 0; - CurMemoLockType = -1; - CurMemoLockCount = 0; -#else - AutoLock = 0; -#endif - -#ifdef XB_MEMO_FIELDS - MemofileName = ""; - MemoHeader.BlockSize = XB_DBT_BLOCK_SIZE; - MemoHeader.Version = 0x03; - mfp = NULL; - mbb = NULL; - CurMemoBlockNo = -1; - mfield1 = 0; - MStartPos = 0; - MFieldLen = 0; - NextFreeBlock = 0L; - FreeBlockCnt = 0L; - MNextBlockNo = 0L; - MNoOfFreeBlocks = 0L; -#endif - -//#ifdef XB_REAL_DELETE - RealDelete = 0; - FirstFreeRec = 0L; - RealNumRecs = 0L; -//#endif -} -/************************************************************************/ -//! Set dbase version for the dbf file. -/*! - Set dbase version. Should only be used before creating a database with - xbDbf::CreateDatabase(). - - \param v version, either 3 or 4. -*/ -xbShort xbDbf::SetVersion(xbShort v) { - if (v == 0) - return XFV; - else - if(v == 3) { - XFV = 3; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x03; -#endif - return XFV; - } else - if (v == 4) { - XFV = 4; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x00; -#endif - return XFV; - } - - return XB_INVALID_OPTION; -} -/************************************************************************/ -//! Write the dbf header -/*! - Internal use only. - - \param PositionOption flag that indicates whether file postition should - be moved. non-zero if so, zero if not. -*/ -xbShort xbDbf::WriteHeader( xbShort PositionOption ) -{ - char buf[32]; - memset(buf, 0, 32); - if(PositionOption) - rewind(fp); - - memcpy(&buf[0], &Version, 4); - xbase->PutLong(&buf[4], NoOfRecs); - xbase->PutShort(&buf[8], HeaderLen ); - xbase->PutShort(&buf[10], RecordLen ); - -#ifdef XB_REAL_DELETE - if(RealDelete){ - xbase->PutULong(&buf[12], FirstFreeRec); - xbase->PutULong(&buf[16], RealNumRecs); - } -#endif - if(fwrite(buf, 32, 1, fp) != 1) - return XB_WRITE_ERROR; - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Read the dbf header. -/*! - Internal use only. - - \param PositionOption -*/ -xbShort xbDbf::ReadHeader( xbShort PositionOption ) -{ -#if 0 - char buf[4]; - if (PositionOption) - rewind(fp); - if (fread(&Version, 4, 1, fp) != 1) - xb_error(XB_READ_ERROR); - - if (fread(buf, 4, 1, fp ) != 1) - xb_error(XB_READ_ERROR); - - NoOfRecs = xbase->GetLong( buf ); - if(fread(buf, 2, 1, fp) != 1) - xb_error(XB_READ_ERROR); - - HeaderLen = xbase->GetShort( buf ); - if(fread(buf, 2, 1, fp) != 1) - xb_error(XB_READ_ERROR); - - RecordLen = xbase->GetShort(buf); - -#ifdef XB_REAL_DELETE - if(RealDelete) - { - if (fread(buf, 4, 1, fp ) != 1) - xb_error(XB_READ_ERROR); - FirstFreeRec = xbase->GetULong( buf ); - - if (fread(buf, 4, 1, fp ) != 1) - xb_error(XB_READ_ERROR); - RealNumRecs = xbase->GetULong( buf ); - } -#endif -#else - char buf[32]; - - if(PositionOption) - rewind(fp); - - if(fread(buf, 32, 1, fp) != 1) - return XB_READ_ERROR; - - memcpy(&Version, buf, 4); - NoOfRecs = xbase->GetLong(&buf[4]); - HeaderLen = xbase->GetShort(&buf[8]); - RecordLen = xbase->GetShort(&buf[10]); - -#ifdef XB_REAL_DELETE - if(RealDelete) - { - FirstFreeRec = xbase->GetULong(&buf[12]); - RealNumRecs = xbase->GetULong(&buf[16]); - } -#endif -#endif - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Determine if file name suffix is missing -/*! - Internal use only. -*/ -xbShort xbDbf::NameSuffixMissing( xbShort type, const char * name ) -{ - /* type 1 is DBF check - type 2 is NDX check - type 3 is MDX check - type 4 is NTX check - - Returns 0 if suffix found - 1 if suffix not found, lower case - 2 is suffix not found, upper, case -*/ - - xbShort len; - - len = strlen( name ); - if( len <= 4 ) - if( name[len-1] >= 'A' && name[len-1] <= 'Z' ) - return 2; - else - return 1; - - if( type == 1 && name[len-4] == '.' && - ( name[len-3] == 'd' || name[len-3] == 'D' ) && - ( name[len-2] == 'b' || name[len-2] == 'B' ) && - ( name[len-1] == 'f' || name[len-1] == 'F' ) - ) - return 0; - - if( type == 2 && name[len-4] == '.' && - ( name[len-3] == 'n' || name[len-3] == 'N' ) && - ( name[len-2] == 'd' || name[len-2] == 'D' ) && - ( name[len-1] == 'x' || name[len-1] == 'X' ) - ) - return 0; - - if( type == 4 && name[len-4] == '.' && - ( name[len-3] == 'n' || name[len-3] == 'N' ) && - ( name[len-2] == 't' || name[len-2] == 'T' ) && - ( name[len-1] == 'x' || name[len-1] == 'X' ) - ) - return 0; - - if( name[len-5] >= 'A' && name[len-5] <= 'Z' ) - return 2; - else - return 1; -} -/************************************************************************/ -//! Create the dbf file. -/*! - This method attempts to create the DBF file with the specified - name (TableName) and schema (xbSchema s). The OverLay switch is used to determine - if an existing file should be overwritten or an error flagged if the - file already exists. The record buffer is blanked (set to spaces). - - \param TableName name of the table - \param s xbSchema - \param Overlay One of the following: - \htmlonly - <p> - <table border=2><tr><th>OverLay</th><th>Description</th></tr> - <tr><td>XB_OVERLAY</td><td>Overwrite existing file if it exists</td></tr> - <tr><td>XB_DONTOVERLAY</td><td>Report an error if file exists</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{OverLay} & \textbf{Description} \\ \hline \hline - XB\_OVERLAY & Overwrite existing file if it exists \\ \hline - XB\_DONTOVERLAY & Report an error if file exists \\ \hline - \end{tabular} - \endlatexonly - \returns One of the following return codes: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_FILE_EXISTS</td><td>If the file exists and OverLay is XB_DONTOVERLAY</td></tr> - <tr><td>XB_OPEN_ERROR</td><td>Couldn't open the file</td></tr> <tr><td>XB_NO_MEMORY</td><td>Memory allocation error</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Couldn't write to disk</td><tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No Error \\ \hline - XB\_FILE\_EXISTS & If the file exists and OverLay is XB\_DONTOVERAY \\ \hline - XB\_OPEN\_ERROR & Couldn't open the file \\ \hline - XB\_WRITE\_ERROR & Couldn't write to disk \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::CreateDatabase( const char * TableName, xbSchema * s, - const xbShort Overlay ) -{ - xbShort i, j, k, k2, rc; /* , count; */ - -#ifdef XB_MEMO_FIELDS - xbShort MemoSw = 0; -#endif - - DbfStatus = XB_CLOSED; - SetFileName( TableName ); - - /* check if the file already exists */ - if((( fp = fopen( GetFileName(), "r" )) != NULL ) && !Overlay ){ - fclose( fp ); - return XB_FILE_EXISTS; - } - else if( fp ) fclose( fp ); - - if(( fp = fopen( GetFileName(), "w+b" )) == NULL ) - return XB_OPEN_ERROR; - -#ifdef XB_LOCKING_ON - /* no buffering in multi user mode */ - setbuf( fp, NULL ); - - /* open the lock file if XB_XBASE_LOCK_FLAVOR */ -// if( LockMode == XB_XBASE_LOCK_MODE ) -// if(( rc = OpenXbLockFile()) != XB_NO_ERROR ) -// return rc; -#endif - - /* count the number of fields and check paramaters */ - i = 0; - while( s[i].Type != 0 ){ - NoOfFields++; - -#ifdef XB_MEMO_FIELDS - if(s[i].Type == 'M'){ - s[i].FieldLen = 10; - s[i].NoOfDecs = 0; - } -#endif /* XB_MEMO_FIELDS */ - - if(s[i].Type == 'D'){ - s[i].FieldLen = 8; - s[i].NoOfDecs = 0; - } - - if(s[i].Type == 'C') - s[i].NoOfDecs = 0; - - RecordLen += s[i].FieldLen; - - if( s[i].Type != 'C' && - s[i].Type != 'N' && - s[i].Type != 'F' && - s[i].Type != 'D' && -#ifdef XB_MEMO_FIELDS - s[i].Type != 'M' && -#endif /* XB_MEMO_FIELDS */ - s[i].Type != 'L' ) - { - fclose( fp ); - InitVars(); - return XB_UNKNOWN_FIELD_TYPE; - } - -#ifdef XB_MEMO_FIELDS -// 8/18/03 types B and O dont exist yet - gkunkel -// if( !MemoSw && ( s[i].Type=='M' || s[i].Type=='B' || s[i].Type=='O')) - if( !MemoSw && ( s[i].Type=='M' )) - MemoSw++; -#endif - -// check for numeric fields which are too long - if((s[i].Type == 'N' || s[i].Type == 'F') && s[i].FieldLen > 19 ){ - fclose( fp ); - InitVars(); - return XB_INVALID_FIELD_LEN; - } - i++; - } - RecordLen++; /* add one byte for 0x0D */ - - if(( RecBuf = (char *) malloc( RecordLen )) == NULL ){ - fclose( fp ); - InitVars(); - return XB_NO_MEMORY; - } - - if(( RecBuf2 = (char *) malloc( RecordLen )) == NULL ){ - free( RecBuf ); - fclose( fp ); - InitVars(); - return XB_NO_MEMORY; - } - - /* BlankRecord(); */ - memset( RecBuf, 0x20, RecordLen ); - memset( RecBuf2, 0x20, RecordLen ); - - /* set class variables */ - Version = XFV & 0x7; // file version - bit 0-2 -#ifdef XB_MEMO_FIELDS - if(MemoSw){ - if((XFV & 0x7) == 3) - Version |= 0x80; // memo presence - bit 7 - else - Version = (char) 0x8b; - } -#endif - - CurRec = 0L; - HeaderLen = 33 + NoOfFields * 32; - xbDate d; - UpdateYY = (d.YearOf() - 1900); - if((XFV & 0x7) == 3) - UpdateYY %= 100; // dBASE III seems to do this, but IV does not. DTB - - UpdateMM = d.MonthOf(); - UpdateDD = d.DayOf( XB_FMT_MONTH ); - - /* write the header prolog */ - if(( rc = WriteHeader( 0 )) != XB_NO_ERROR ){ - free( RecBuf ); - free( RecBuf2 ); - fclose( fp ); - InitVars(); - return XB_WRITE_ERROR; - } - - if((SchemaPtr=(xbSchemaRec *)malloc(NoOfFields*sizeof(xbSchemaRec)))==NULL){ - free( RecBuf ); - free( RecBuf2 ); - fclose( fp ); - InitVars(); - return XB_NO_MEMORY; - } - memset( SchemaPtr, 0x00, ( NoOfFields * sizeof(xbSchemaRec))); - - /* write the field information into the header */ - for( i = 0, k = 1; i < NoOfFields; i++ ){ - memset( SchemaPtr[i].FieldName, 0x00, 11 ); - strncpy( SchemaPtr[i].FieldName, s[i].FieldName, 10 ); - - SchemaPtr[i].Type = s[i].Type; - SchemaPtr[i].FieldLen = s[i].FieldLen; - SchemaPtr[i].NoOfDecs = s[i].NoOfDecs; - - if( SchemaPtr[i].NoOfDecs > SchemaPtr[i].FieldLen ) { - fclose( fp ); - free( SchemaPtr ); - free( RecBuf ); - free( RecBuf2 ); - InitVars(); - return XB_INVALID_SCHEMA; - } - - k2 = k; - k += SchemaPtr[i].FieldLen; - - if(( fwrite( &SchemaPtr[i], 1, 18, fp )) != 18 ) { - fclose( fp ); - free( SchemaPtr ); - free( RecBuf ); - free( RecBuf2 ); - InitVars(); - return XB_WRITE_ERROR; - } - - for( j = 0; j < 14; j++ ) { - if(( fwrite( "\x00", 1, 1, fp )) != 1 ) { - free( SchemaPtr ); - free( RecBuf ); - free( RecBuf2 ); - fclose( fp ); - InitVars(); - return XB_WRITE_ERROR; - } - } - SchemaPtr[i].Address = RecBuf + k2; - SchemaPtr[i].Address2 = RecBuf2 + k2; - } - - /* write the header terminator */ - if(( fputc( XB_CHARHDR, fp )) != XB_CHARHDR ){ - fclose( fp ); - free( SchemaPtr ); - free( RecBuf ); - free( RecBuf2 ); - InitVars(); - return XB_WRITE_ERROR; - } - -#ifdef XB_MEMO_FIELDS - if( MemoSw ) - if((rc = CreateMemoFile()) != XB_NO_ERROR){ - fclose(fp); - free(RecBuf); - free(RecBuf2); - InitVars(); - return rc; - } -#endif - - DbfStatus = XB_OPEN; - return xbase->AddDbfToDbfList(this, GetFileName()); -} -/************************************************************************/ -//! Close the dbf file. -/*! - This method attempts to close the DBF file which was previously - opened with either CreateDatabase() or OpenDatabase(). Deletes any - memory allocated. Automatically closes any open indexes associated - with this data file. - - \param deleteIndexes if TRUE, the indexes (xbIndex instances) will also - be deleted (index files will not be deleted) - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File was not open</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No Error \\ \hline - XB\_NOT\_OPEN\_ERROR & File was not open \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::CloseDatabase( xbBool deleteIndexes ) -{ -#if defined(XB_INDEX_ANY) - xbIxList *i, *ti; -#endif - - if(DbfStatus == XB_CLOSED) - return XB_NO_ERROR; - - -#if defined(XB_INDEX_ANY) - i = NdxList; - while (i){ - i->index->CloseIndex(); - if(deleteIndexes) - delete i->index; - i = NdxList; - } -/* free up unused nodes */ - i = FreeIxList; - while( i ) { - ti = i; - i = i->NextIx; - free(ti); - } -#endif - - if(SchemaPtr){ - for( int j = 0; j < NoOfFields; j++ ) - if( SchemaPtr[j].fp ) delete SchemaPtr[j].fp; - free( SchemaPtr ); - } - if(RecBuf) - free( RecBuf ); - if(RecBuf2) - free( RecBuf2 ); - -#ifdef XB_MEMO_FIELDS - if( mbb ) - free( mbb ); /* memo block buffer */ - if( mfp ) - fclose( mfp ); /* memo file pointer */ -#endif - -#ifdef XB_LOCKING_ON - if( xblfh ){ - fclose( xblfh ); - xblfh = NULL; - } -#endif - - xbase->RemoveDbfFromDbfList( this ); - if(fp) - fclose( fp ); - InitVars(); - return XB_NO_ERROR; -} -/************************************************************************/ -/* options 1 = Print header only - 2 = Field data only - 3 = Header and Field data */ - -//! Dump header information. -/*! - \param Option One of the following: - \htmlonly - <p> - <table border=2><tr><th>Option</th><th>Description</th></tr> - <tr><td>1</td><td>Print header only</td></tr> - <tr><td>2</td><td>Field data only</td></tr> - <tr><td>3</td><td>Header and field data</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Option} & \textbf{Description} \\ \hline \hline - 1 & Header only \\ \hline - 2 & Field data only \\ \hline - 3 & Header and field data \\ \hline - \end{tabular} - \endlatexonly -*/ -#ifdef XBASE_DEBUG -xbShort xbDbf::DumpHeader( xbShort Option ) -{ - int i; - - if( Option < 1 || Option > 3 ) - return XB_INVALID_OPTION; - - if( DbfStatus == XB_CLOSED ) - return XB_NOT_OPEN; - - std::cout << "\nDatabase file " << GetFileName() << std::endl << std::endl; - - if( Option != 2 ){ - std::cout << "File header data:" << std::endl; - if( Version == 3 ) - std::cout << "Dbase III file" << std::endl; - else if ( Version == 83 ) - std::cout << "Dbase III file with memo fields" << std::endl << std::endl; - - std::cout << "Last update date = " - << (int) UpdateMM << "/" << (int) UpdateDD << "/" << (int) UpdateYY % 100 << std::endl; - - std::cout << "Header length = " << HeaderLen << std::endl; - std::cout << "Record length = " << RecordLen << std::endl; - std::cout << "Records in file = " << NoOfRecs << std::endl << std::endl; -#ifdef XB_REAL_DELETE - std::cout << "First Free Rec = " << FirstFreeRec << std::endl << std::endl; -#endif - } - if( Option != 1 ){ - std::cout << "Field Name Type Length Decimals" << std::endl; - std::cout << "---------- ---- ------ --------" << std::endl; - for( i = 0; i <NoOfFields; i++ ){ - if( SchemaPtr[i].Type == 'C' && SchemaPtr[i].NoOfDecs > 0 ) - printf( "%10s %1c %4d %4d\n", SchemaPtr[i].FieldName, - SchemaPtr[i].Type, SchemaPtr[i].FieldLen, 0 ); - else - printf( "%10s %1c %4d %4d\n", SchemaPtr[i].FieldName, - SchemaPtr[i].Type, SchemaPtr[i].FieldLen, SchemaPtr[i].NoOfDecs ); - } - } - std::cout << std::endl; - return XB_NO_ERROR; -} -#endif -/************************************************************************/ -//! Open the DBF file. -/*! - This method attempts to open the DBF file with the specified - name (TableName). This method does not position to any particular - record in the file. The record buffer is blanked (set to spaces). - - \param TableName Name of table to open - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_OPEN_ERROR</td><td>Couldn't open file</td></tr> - <tr><td>XB_NO_MEMORY</td><td>Memory allocation error</td></tr> - <tr><td>XB_NOT_XBASE</td><td>Not an DBF file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_OPEN\_ERROR & Couldn't open file \\ \hline - XB\_NO\_MEMORY & Memory allocation error \\ \hline - XB\_NOT\_XBASE & Not an DBF file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::OpenDatabase( const char * TableName ) -{ - xbShort i, j, rc; - char buf[33]; - char *p; - -#ifdef XB_MEMO_FIELDS - xbShort MemoSw = 0; -#endif - - /* verify the file is not already open */ - if( DbfStatus != XB_CLOSED ) - return XB_ALREADY_OPEN; - - /* copy the file name to the class variable */ - SetFileName( TableName ); - - /* open the file */ - if(( fp = fopen(GetFileName(), "r+b")) == NULL ){ - // - // Try to open read only if failed to open read/write - // - if(( fp = fopen(GetFileName(), "rb")) == NULL ) - return XB_OPEN_ERROR; - } - -#ifdef XB_LOCKING_ON - /* no buffering in multi user mode - may not see what others have updated */ - setbuf( fp, NULL ); - - /* open the lock file if XB_XBASE_LOCK_MODE */ -// if( LockMode == XB_XBASE_LOCK_MODE ) -// if(( rc = OpenXbLockFile()) != XB_NO_ERROR ) -// return rc; -#endif - -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR) -// return rc; -#endif - - /* copy the header into memory */ - if(( rc = ReadHeader( 1 )) != XB_NO_ERROR ){ - InitVars(); - return rc; - } - - /* check the version */ - if( Version == 3 || Version == (char)0x83 ){ /* dBASE III+ */ - XFV = 3; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x03; -#endif - } - else if( Version == 4 || Version == (char)0x8B ){ /* dBASE IV */ - XFV = 4; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x00; -#endif - } - else if( Version == (char)0xf5 ){ /* FoxPro */ - XFV = 4; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x00; -#endif - } - else if( Version == (char)0x30 ){ /* Visual Foxpro */ - XFV = 4; -#ifdef XB_MEMO_FIELDS - MemoHeader.Version = 0x00; -#endif - } else { - InitVars(); - return XB_NOT_XBASE; - } - - // it would seem that dBASE III+ generates an UpdateYY value - // of 0 for 2000 and dBASE IV uses 100, so I have removed the - // check for UpdateYY being 0 (which might be valid). DTB - - // Not all flavors of database tools use these fields - // Found a month set to 0 in valid dbf file - // Commented out this check 2/11/06 - GAK - - // if( UpdateMM == 0 || UpdateDD == 0 ){ - // InitVars(); - // return XB_NOT_XBASE; - // } - - /* calculate the number of fields */ - if( Version == (char)0x30 ) { - NoOfFields = ( HeaderLen - 296 ) / 32 ; - } else { - NoOfFields = ( HeaderLen - 33 ) / 32; - } - - if(( RecBuf = (char *) malloc( RecordLen )) == NULL ) { - fclose( fp ); - InitVars(); - return XB_NO_MEMORY; - } - if(( RecBuf2 = (char *) malloc( RecordLen )) == NULL ) { - fclose( fp ); - free( RecBuf ); - InitVars(); - return XB_NO_MEMORY; - } - - if((SchemaPtr=(xbSchemaRec *)malloc(NoOfFields*sizeof(xbSchemaRec)))==NULL){ - free( RecBuf ); - free( RecBuf2 ); - fclose( fp ); - InitVars(); - return XB_NO_MEMORY; - } - memset( SchemaPtr, 0x00, ( NoOfFields * sizeof(xbSchemaRec))); - - /* copy field info into memory */ - for( i = 0, j = 1; i < NoOfFields; i++ ){ - _fseek( fp,((xbOffT)i*32+32), 0 ); - fread( &buf, 1, 32, fp ); - p = buf; - strncpy( SchemaPtr[i].FieldName, p, 10 ); - p += 11; - SchemaPtr[i].Type = *p++; - - SchemaPtr[i].Address = RecBuf + j; - SchemaPtr[i].Address2 = RecBuf2 + j; - - SchemaPtr[i].FieldLen = *( p + 4 ); - SchemaPtr[i].NoOfDecs = *( p + 5 ); - - if( SchemaPtr[i].Type == 'C' && SchemaPtr[i].NoOfDecs > 0 ){ - SchemaPtr[i].LongFieldLen = xbase->GetShort( p + 4 ); - j += SchemaPtr[i].LongFieldLen; - } - else - j += SchemaPtr[i].FieldLen; -#ifdef XB_MEMO_FIELDS - if( !MemoSw && (SchemaPtr[i].Type == 'M' || - SchemaPtr[i].Type == 'B' || SchemaPtr[i].Type == 'O' )) - MemoSw++; -#endif - } - CurRec = 0L; - BlankRecord(); - DbfStatus = XB_OPEN; - -#ifdef XB_MEMO_FIELDS - if( MemoSw ) /* does this table have memo fields ? */ - if(( rc = OpenMemoFile()) != XB_NO_ERROR ){ - free( RecBuf ); - free( RecBuf2 ); - free( SchemaPtr ); - fclose( fp ); - InitVars(); - return rc; - } -#endif - -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// LockDatabase( XB_UNLOCK, 0L ); -#endif /* XB_LOCKING_ON */ - - return xbase->AddDbfToDbfList( this, GetFileName() ); -} -/************************************************************************/ -//! Blank the record buffer. -/*! - Sets the record to spaces. -*/ -xbShort xbDbf::BlankRecord() -{ - if( DbfStatus == XB_CLOSED ) - return XB_NOT_OPEN; - - if( DbfStatus != XB_UPDATED ){ - DbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, RecordLen ); - } - - memset( RecBuf, 0x20, RecordLen ); - return XB_NO_ERROR; -} -/************************************************************************/ -//! Append the current record to the data file -/*! - This method attempts to append the contents of the current record buffer - to the end of the DBF file and updates the file date and number of - records in the file. Also updates any open indices associated with - this data file. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::AppendRecord() -{ - xbShort rc; - xbULong nextRecNo; - -#if defined(XB_INDEX_ANY) - xbIxList *i; -#endif - -/* lock the database */ -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR) -// return rc; - - rc = ReadHeader(1); - -// if(AutoLock) -// LockDatabase( XB_UNLOCK, 0L ); - - if( rc ) - return rc; - -#endif - -/* lock any indexes */ -#if defined(XB_INDEX_ANY) -#ifdef XB_LOCKING_ON - i = NdxList; - while( i && AutoLock ){ -// if(( rc = i->index->LockIndex( XB_LOCK )) != XB_NO_ERROR ) -// return rc; - i = i->NextIx; - } -#endif /* XB_LOCKING_ON */ -#endif - -// if there are no duplicates, and no records set the CurRec to the -// last record + 1. This is for EXP::RECNO() - -/* check for any duplicate keys */ -#if defined(XB_INDEX_ANY) - i = NdxList; - while( i ){ - if( i->index->UniqueIndex() ){ - i->index->CreateKey( 0, 0 ); - if( i->index->FindKey() == XB_FOUND ) - return XB_KEY_NOT_UNIQUE; - } - i = i->NextIx; - } -#endif - -#ifdef XB_REAL_DELETE - if(RealDelete && FirstFreeRec) - nextRecNo = FirstFreeRec; - else - nextRecNo = NoOfRecs + 1; -#else - nextRecNo = NoOfRecs + 1; -#endif - - CurRec = NoOfRecs + 1; - -#if defined(XB_INDEX_ANY) -/* update the indexes */ - i = NdxList; - while( i ){ - if( !i->index->UniqueIndex() ) /* if we didn't prepare the key */ - if(( rc = i->index->CreateKey( 0, 0 )) != XB_NO_ERROR ) /* then do it before the add */ - return rc; - if(( rc = i->index->AddKey(nextRecNo)) != XB_NO_ERROR ) - return rc; - i->index->TouchIndex(); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ - -#ifdef XB_REAL_DELETE - char buf[4]; - - if(RealDelete && FirstFreeRec){ - /* - ** Grab the next free rec no and put it in FirstFreeRec - */ - if(_fseek(fp, (HeaderLen+(((xbOffT)FirstFreeRec-1)*RecordLen)+1), 0) != 0) - return XB_SEEK_ERROR; - - if(fread(buf, 4, 1, fp) != 1) - return XB_READ_ERROR; - - FirstFreeRec = xbase->GetULong(buf); - } - - /* - ** Okay, seek and write the record out - */ - if(_fseek(fp, (HeaderLen+(((xbOffT)nextRecNo-1)*RecordLen)), 0) != 0) - return XB_SEEK_ERROR; - - if(fwrite( RecBuf, RecordLen, 1, fp) != 1) - return XB_WRITE_ERROR; - - /* - ** If we just appended the record to the file, then write the EOF char - */ - if(nextRecNo == NoOfRecs + 1){ - if( fputc( XB_CHAREOF, fp ) != XB_CHAREOF ) - return XB_WRITE_ERROR; - } -#else - /* write the last record */ - if( _fseek( fp,(HeaderLen+((xbOffT)NoOfRecs*RecordLen)), 0 ) != 0 ) - return XB_SEEK_ERROR; - - if( fwrite( RecBuf, RecordLen, 1, fp ) != 1 ) - return XB_WRITE_ERROR; - - /* write the end of file marker */ - if( fputc( XB_CHAREOF, fp ) != XB_CHAREOF ) - return XB_WRITE_ERROR; -#endif - - /* calculate the latest header information */ - xbDate d; - UpdateYY = d.YearOf() - 1900; - if(XFV == 3) - UpdateYY %= 100; // dBASE III seems to do this, IV does not. DTB - UpdateMM = d.MonthOf(); - UpdateDD = d.DayOf( XB_FMT_MONTH ); -#ifndef XB_REAL_DELETE - NoOfRecs++; -#else - if(RealDelete){ - if(nextRecNo == NoOfRecs + 1) - NoOfRecs++; - RealNumRecs++; - } - else - NoOfRecs++; -#endif - CurRec = nextRecNo; - - /* rewrite the header record */ - if(( rc = WriteHeader( 1 )) != XB_NO_ERROR ) - return rc; - -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// LockDatabase( XB_UNLOCK, 0L ); - -#if defined(XB_INDEX_ANY) - i = NdxList; - while( i && AutoLock ){ -// i->index->LockIndex( XB_UNLOCK ); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ -#endif /* XB_LOCKING_ON */ - - DbfStatus = XB_OPEN; - return XB_NO_ERROR; -} -/************************************************************************/ -//! Get a record from the data file -/*! - This method attempts to retrieve the record specified by RecNo from the - data file into the record buffer. - - \param RecNo Record number to retrieve - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::GetRecord( xbULong RecNo ) -{ - xbShort rc; - if( DbfStatus == XB_CLOSED ) - return XB_NOT_OPEN; - -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// if(( rc = LockDatabase( XB_LOCK, RecNo )) != 0 ) return rc; - - rc = ReadHeader(1); - -// if(AutoLock) -// LockDatabase( XB_UNLOCK, RecNo ); - - if( rc ) - return rc; - -#endif - - if( RecNo > NoOfRecs || RecNo == 0L ) - return XB_INVALID_RECORD; - - if( _fseek( fp, (HeaderLen+(((xbOffT)RecNo-1L)*RecordLen)), SEEK_SET )){ -#ifdef XB_LOCKING_ON -// LockDatabase( XB_UNLOCK, RecNo ); -#endif - return XB_SEEK_ERROR; - } - - if( fread( RecBuf, RecordLen, 1, fp ) != 1 ){ -#ifdef XB_LOCKING_ON -// LockDatabase( XB_UNLOCK, RecNo ); -#endif - return XB_READ_ERROR; - } - -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// LockDatabase( XB_LOCK, RecNo ); -#endif - - DbfStatus = XB_OPEN; - CurRec = RecNo; - return XB_NO_ERROR; -} -/************************************************************************/ -//! Get the first physical record in the data file -/*! - Attempts to retrieve the first physical record from the data file into - the record buffer. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::GetFirstRecord() -{ - xbShort rc; - if( NoOfRecs == 0 ) - return XB_INVALID_RECORD; - - rc = GetRecord( 1L ); -#ifdef XB_REAL_DELETE - if(!rc && RealDelete && RecordDeleted()) - rc = GetNextRecord(); -#endif - - return rc; -} -/************************************************************************/ -//! Get the last phyiscal record in the data file -/*! - Attempts to retrieve the last physical record from the data file into - the record buffer. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_EOF</td><td>At end of file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_EOF & At end of file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::GetLastRecord() -{ - xbShort rc; - if( NoOfRecs == 0 ) - return XB_INVALID_RECORD; - - rc = GetRecord( NoOfRecs ); -#ifdef XB_REAL_DELETE - if(!rc && RealDelete && RecordDeleted()) - rc = GetPrevRecord(); -#endif - - return rc; -} -/************************************************************************/ -//! Get the next physical record in the data file -/*! - Attempts to retrieve the next physical record from the data file into - the record buffer. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_EOF</td><td>At end of file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_EOF & At end of file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::GetNextRecord() -{ - xbShort rc; - if( NoOfRecs == 0 ) - return XB_INVALID_RECORD; - else if( CurRec >= NoOfRecs ) - return XB_EOF; - - rc = GetRecord( ++CurRec ); - -#ifdef XB_REAL_DELETE - while(!rc && RealDelete && RecordDeleted()) - rc = GetRecord(++CurRec); -#endif - - return rc; -} -/************************************************************************/ -//! Get the previous physical record in the data file -/*! - Attempts to retrieve the previous physical record from the data file into - the record buffer. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_BOF</td><td>At beginning of file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_BOF & At beginning of file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::GetPrevRecord() -{ - xbShort rc; - if( NoOfRecs == 0 ) - return XB_INVALID_RECORD; - else if( CurRec <= 1L ) - return XB_EOF; - - rc = GetRecord( --CurRec ); - -#ifdef XB_REAL_DELETE - while(!rc && RealDelete && RecordDeleted()) - rc = GetRecord(--CurRec); -#endif - - return rc; -} -/************************************************************************/ -//! Dump record -/*! - Dump the contents of the specified record to stdout. - - \param RecNo Record number of record to be dumped. - \returns An error code (same as GetRecord()). -*/ -xbShort xbDbf::DumpRecord( xbULong RecNo ) -{ - int i, rc; - char buf[4096]; - - if( RecNo == 0 || RecNo > NoOfRecs ) - return XB_INVALID_RECORD; - - rc = GetRecord( RecNo ); - if( rc != XB_NO_ERROR ) - return rc; - - std::cout << "\nREC NUMBER " << RecNo << "\n"; - - if( RecordDeleted() ) - std::cout << "\nRecord deleted...\n"; - - for( i = 0; i < NoOfFields; i++ ){ -#ifdef XB_MEMO_FIELDS - if(SchemaPtr[i].Type == 'M'){ - if( MemoFieldExists( i )){ - std::cout << SchemaPtr[i].Type << " " << SchemaPtr[i].FieldName - << " len = " << GetMemoFieldLen( i ) << std::endl; - memset( buf, 0x00, 4095 ); - rc = GetMemoField(i, 4095, buf, 0); - if(rc != XB_NO_ERROR) - return rc; - } else { - buf[0] = 0x00; - } - } - else - GetField( i, buf ); - std::cout << SchemaPtr[i].Type << " " << SchemaPtr[i].FieldName << " = '" << buf << "'\n"; -#else - GetField( i, buf ); - std::cout << SchemaPtr[i].FieldName << " = '" << buf << "'\n"; -#endif - } - std::cout << std::endl; - return XB_NO_ERROR; -} -/************************************************************************/ -//! Write the current record buffer to the current record in the data file. -/*! - Attempts to write the contents of the record buffer to the current - record in the data file. Updates any open indexes. - - \sa PutRecord(xbULong RecNo) - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ - -/************************************************************************/ -xbShort xbDbf::PutRecord() { - return PutRecord(CurRec); -} - -//! Write the current record buffer to the specified record in the data file. -/*! - Attempts to write the contents of the record buffer to the record specified - by RecNo. Updates any open indexes. - - \param RecNo Record number to which data should be written - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Couldn't lock file</td></tr> - <tr><td>XB_NOT_OPEN</td><td>File is not open</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Error writing to file</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_LOCK\_FAILED & Couldn't lock file \\ \hline - XB\_NOT\_OPEN & File is not open \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_WRITE\_ERROR & Error writing to file \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::PutRecord(xbULong RecNo) -{ - xbShort rc; - -#if defined(XB_INDEX_ANY) - xbIxList *i; -#endif - - if( DbfStatus == XB_CLOSED ) - return XB_NOT_OPEN; - -/* lock the database */ -#ifdef XB_LOCKING_ON - if( AutoLock ){ -// if(( rc = LockDatabase( XB_LOCK, RecNo )) != XB_NO_ERROR ) -// return rc; -// if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR ){ -// LockDatabase( XB_UNLOCK, RecNo ); -// return rc; -// } - - if((rc = ReadHeader(1)) != XB_NO_ERROR){ -// if(AutoLock){ -// LockDatabase( XB_UNLOCK, RecNo ); -// LockDatabase( XB_UNLOCK, 0L ); -// } - return rc; - } - } -#endif - - if( RecNo > NoOfRecs || RecNo == 0L ) - return XB_INVALID_RECORD; - -/* lock the indexes */ -#if defined(XB_INDEX_ANY) -#ifdef XB_LOCKING_ON - i = NdxList; - while( i && AutoLock ){ -// if(( rc = i->index->LockIndex( XB_LOCK )) != XB_NO_ERROR ) -// return rc; - i = i->NextIx; - } -#endif /* XB_LOCKING_ON */ -#endif - -#if defined(XB_INDEX_ANY) - /* for any unique indexes that were updated, verify no unique keys exist */ - i = NdxList; - while( i ){ - if( i->index->UniqueIndex() ){ - if(( i->KeyUpdated = i->index->KeyWasChanged()) == 1 ){ - i->index->CreateKey(0, 0); - if( i->index->FindKey() == XB_FOUND && i->index->GetCurDbfRec() != RecNo) - return XB_KEY_NOT_UNIQUE; - } - } - i = i->NextIx; - } -#endif - -#if defined(XB_INDEX_ANY) - /* loop through deleting old index keys and adding new index keys */ - i = NdxList; - while( i ){ - if( !i->index->UniqueIndex() ) - i->KeyUpdated = i->index->KeyWasChanged(); - if( i->KeyUpdated ){ - i->index->CreateKey( 1, 0 ); /* load key buf w/ old values */ - if((rc = i->index->DeleteKey( CurRec )) != XB_NO_ERROR){ -#ifdef XB_LOCKING_ON -// if( AutoLock ){ -// LockDatabase( XB_UNLOCK, RecNo ); -// LockDatabase( XB_UNLOCK, 0L ); -// } -#if defined(XB_INDEX_ANY) - i = NdxList; - while( i && AutoLock ){ -// i->index->LockIndex( XB_UNLOCK ); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ -#endif /* XB_LOCKING_ON */ - return rc; - } - - i->index->CreateKey( 0, 0 ); - if(( rc = i->index->AddKey(CurRec)) != XB_NO_ERROR ){ -#ifdef XB_LOCKING_ON -// if( AutoLock ){ -// LockDatabase( XB_UNLOCK, RecNo ); -// LockDatabase( XB_UNLOCK, 0L ); -// } -#if defined(XB_INDEX_ANY) - i = NdxList; - while( i && AutoLock ){ -// i->index->LockIndex( XB_UNLOCK ); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ -#endif /* XB_LOCKING_ON */ - return rc; - } - i->index->TouchIndex(); - } - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ - - if( _fseek( fp, (HeaderLen+(((xbOffT)RecNo-1L)*RecordLen)),0 )) - return XB_SEEK_ERROR; - - if( fwrite( RecBuf, RecordLen, 1, fp ) != 1 ) - return XB_WRITE_ERROR; - - /* calculate the latest header information */ - xbDate d; - UpdateYY = d.YearOf() - 1900; - if(XFV == 3) - UpdateYY %= 100; // dBASE III seems to do this, IV does not. DTB - UpdateMM = d.MonthOf(); - UpdateDD = d.DayOf( XB_FMT_MONTH ); - - /* rewrite the header record */ - if(( rc = WriteHeader( 1 )) != XB_NO_ERROR ) - return rc; - -#ifdef XB_LOCKING_ON -// if( AutoLock ){ -// LockDatabase( XB_UNLOCK, RecNo ); -// LockDatabase( XB_UNLOCK, 0L ); -// } - -#if defined(XB_INDEX_ANY) - i = NdxList; - while( i && AutoLock ){ -// i->index->LockIndex( XB_UNLOCK ); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ -#endif /* XB_LOCKING_ON */ - - CurRec = RecNo; - DbfStatus = XB_OPEN; - return XB_NO_ERROR; -} -/************************************************************************/ -//! Delete the current record -/*! - Marks the current record as deleted or if "real" deletes are turned - on (xbDbf::RealDeleteOn()) will delete the record and add it to the - free record list. Normal dBase behavior is to simply mark the record - as deleted; the record will actually be deleted when the the DBF file - "packed" (xbDbf::PackDatabase()). If "real" deletes are not on, a - record may be undeleted using xbDbf::UndeleteRecord(). - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::DeleteRecord() -{ - xbULong newCurRec = 0; - xbShort rc = XB_NO_ERROR; - -#if defined(XB_INDEX_ANY) - xbIxList *i; -#endif - - if(!RecBuf) - return XB_INVALID_RECORD; - - if(CurRec < 1 || CurRec > NoOfRecs) - return XB_INVALID_RECORD; - -/* lock the database */ -#ifdef XB_LOCKING_ON - - if( AutoLock ){ -/* - if(( rc = LockDatabase( XB_LOCK, CurRec )) != XB_NO_ERROR ) - return rc; - if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR ){ - LockDatabase( XB_UNLOCK, CurRec ); - return rc; - } - */ - if((rc = ReadHeader(1)) != XB_NO_ERROR){ -// if(AutoLock){ -// LockDatabase( XB_UNLOCK, CurRec ); -// LockDatabase( XB_UNLOCK, 0L ); -// } - return rc; - } - } -#endif - -/* lock the indexes */ -#if defined(XB_INDEX_ANY) && defined(XB_LOCKING_ON) && defined(XB_REAL_DELETE) - i = NdxList; - while( i && AutoLock ){ -// if(( rc = i->index->LockIndex( XB_LOCK )) != XB_NO_ERROR ) -// return rc; - i = i->NextIx; - } -#endif - -/* remove keys from indexes */ -#if defined(XB_REAL_DELETE) && defined(XB_INDEX_ANY) - - if(RealDelete){ - i = NdxList; - while(i){ - i->index->CreateKey(0, 0); /* load key buf */ - if(i->index->GetCurDbfRec() == (xbULong)CurRec){ - i->index->DeleteKey(CurRec); - newCurRec = i->index->GetCurDbfRec(); - } - else - i->index->DeleteKey(CurRec); - i->index->TouchIndex(); - i = i->NextIx; - } - } - -#endif - - RecBuf[0] = 0x2a; - - -#ifdef XB_REAL_DELETE - if(RealDelete){ -#ifdef XB_MEMO_FIELDS - // - // Delete memo data for memo fields. - // - for(int f = 0; f < NoOfFields; f++ ) - if(GetFieldType(f) == 'M' && MemoFieldExists(f)) - UpdateMemoData(f, 0, 0, XB_LOCK); -#endif - xbase->PutULong(&RecBuf[1], FirstFreeRec); - FirstFreeRec = CurRec; - RealNumRecs--; - WriteHeader(1); - } -#endif - - if(!RealDelete){ - if( DbfStatus != XB_UPDATED ){ - DbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, RecordLen ); - } - rc = PutRecord( CurRec ); - } - else - { - if(_fseek( fp, (HeaderLen+(((xbOffT)CurRec-1L)*RecordLen)), 0)) - return XB_SEEK_ERROR; - if(fwrite( RecBuf, RecordLen, 1, fp ) != 1 ) - return XB_WRITE_ERROR; - - // - // Attempt to read in the record for the current location - // in the active index. - // - CurRec = newCurRec; - if(CurRec) - rc = GetRecord(CurRec); - else - BlankRecord(); - } - -#ifdef XB_LOCKING_ON -// if(AutoLock){ -// LockDatabase( XB_UNLOCK, CurRec ); -// LockDatabase( XB_UNLOCK, 0L ); -// } - -#if defined(XB_INDEX_ANY) && defined(XB_REAL_DELETE) - i = NdxList; - while( i && AutoLock ){ -// i->index->LockIndex( XB_UNLOCK ); - i = i->NextIx; - } -#endif /* XB_INDEX_ANY */ -#endif /* XB_LOCKING_ON */ - - return rc; -} -/************************************************************************/ -//! Undelete the current record -/*! - Marks the currect record as not deleted (i.e. removes the flag indicating - the record is deleted). This method may not be used (and will return - an error code) if "real" deletes are on. - - \returns One of the following: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No error \\ \hline - XB\_INVALID\_RECORD & Invalid record number \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::UndeleteRecord() -{ - xbShort rc; - -#ifdef XB_REAL_DELETE - if(RealDelete) - return XB_INVALID_RECORD; -#endif - if( RecBuf ){ - if( DbfStatus != XB_UPDATED ){ - DbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, RecordLen ); - } - - RecBuf[0] = 0x20; - if(( rc = PutRecord( CurRec )) != 0 ) - return rc; - } - else - return XB_INVALID_RECORD; - - return 0; -} -/************************************************************************/ -//! Determine if current record is deleted -/*! - \returns TRUE (1) if the current record is marked as deleted or FALSE - (0) if not. -*/ -xbShort xbDbf::RecordDeleted() -{ - if( RecBuf && RecBuf[0] == 0x2a ) - return 1; - else - return 0; -} -/************************************************************************/ -//! Create a unique file name -/*! -*/ -xbShort xbDbf::CreateUniqueDbfName( xbString & sDbfn, xbString & sDbtn ) -{ - xbShort dnf; /* directory in name flag */ - xbShort unique = 0; - xbLong l = 1; - char dbfn[13]; - char dbtn[13]; - - dnf = xbase->DirectoryExistsInName( GetFileName() ); - sprintf( dbfn, "xb%06d.dbf", l ); - sprintf( dbtn, "xb%06d.dbt", l++ ); - - if( dnf ){ - sDbfn.assign( GetFileName(), 0, dnf ); - sDbfn += dbfn; - sDbtn.assign( GetFileName(), 0, dnf ); - sDbtn += dbtn; - } else { - sDbfn = dbfn; - sDbtn = dbtn; - } - - while( !unique ){ - if( access( sDbfn.getData(), 0 ) == -1 && - access( sDbtn.getData(), 0 ) == -1 ) - unique++; - else{ - sprintf( dbfn, "xb%06d.dbf", l ); - sprintf( dbtn, "xb%06d.dbt", l++ ); - - if( dnf ){ - sDbfn.assign( GetFileName(), 0, dnf ); - sDbfn += dbfn; - sDbtn.assign( GetFileName(), 0, dnf ); - sDbtn += dbtn; - } else { - sDbfn = dbfn; - sDbtn = dbtn; - } - } - } - return 0; -} - -/************************************************************************/ -//! Pack data file -/*! -*/ -xbShort xbDbf::PackDatafiles(void (*statusFunc)(xbLong itemNum, xbLong numItems)) -{ - xbShort rc, i; - FILE *t; - xbLong l; - char *target, *source; - xbString TempDbfName; - xbString TempDbtName; - char * Buf = 0; - -#ifdef XB_MEMO_FIELDS - char tbuf[4]; -#endif - -#ifdef XB_MEMO_FIELDS - xbLong len, BufSize; - xbShort MemoFields; -#endif /* XB_MEMO_FIELDS */ - - xbDbf Temp( xbase ); - CreateUniqueDbfName( TempDbfName, TempDbtName ); - - if(( t = fopen( TempDbfName, "w+b" )) == NULL ) - return XB_OPEN_ERROR; - - /* copy file header */ - if(( rc = _fseek( fp, 0, SEEK_SET )) != 0 ) - return XB_SEEK_ERROR; - - for( i = 0; i < HeaderLen; i++ ) - fputc( fgetc( fp ), t ); - fputc( 0x1a, t ); - - if( fclose( t ) != 0 ) - return XB_CLOSE_ERROR; - -#ifdef XB_MEMO_FIELDS - if(( MemoFields = MemoFieldsPresent()) > 0 ){ - - if((t = fopen( TempDbtName, "w+b" )) == NULL) - return XB_OPEN_ERROR; - - l = 1L; - memset( tbuf, 0x00, 4 ); - xbase->PutLong( tbuf, l ); - - if((fwrite(&tbuf, 4, 1, t)) != 1) - return XB_WRITE_ERROR; - - if( MemoHeader.Version == 0x03 ){ - for( i = 0; i < 12; i++ ) fputc( 0x00, t ); - fputc( 0x03, t ); - for( i = 0; i < 495; i++ ) fputc( 0x00, t ); - } else { - for( i = 0; i < 4; i++ ) fputc( 0x00, t ); - if ((fwrite(&MemoHeader.FileName, 8, 1, t)) != 1) - return XB_WRITE_ERROR; - for( i = 0; i < 4; i++ ) fputc( 0x00, t ); - memset( tbuf, 0x00, 2 ); - xbase->PutShort( tbuf, MemoHeader.BlockSize ); - if ((fwrite(&tbuf, 2, 1, t)) != 1) - return XB_WRITE_ERROR; - - for( i = 22; i < MemoHeader.BlockSize; i++ ) fputc( 0x00, t ); - } - - if( fclose( t ) != 0 ) - return XB_CLOSE_ERROR; - } -#endif /* XB_MEMO_FIELDS */ - - /* reopen as database */ - if(( rc = Temp.OpenDatabase( TempDbfName )) != XB_NO_ERROR ) - return rc; - -#ifdef XB_REAL_DELETE - if(RealDelete) - Temp.RealDeleteOn(); - Temp.FirstFreeRec = 0; - Temp.RealNumRecs = 0; -#endif - Temp.ResetNoOfRecs(); - Temp.WriteHeader(2); // flush NoOfRecs=0 to disk - target = Temp.GetRecordBuf(); - source = GetRecordBuf(); - - for( l = 1; l <= PhysicalNoOfRecords(); l++ ){ - if(statusFunc && (l == 1 || !(l % 100) || l == PhysicalNoOfRecords())) - statusFunc(l, PhysicalNoOfRecords()); - - if(( rc = GetRecord( l )) != XB_NO_ERROR ) - return rc; - - if( !RecordDeleted() ){ - memcpy( target, source, GetRecordLen()); - -#ifdef XB_MEMO_FIELDS - BufSize = 0L; -// Buf = NULL; Already set to 0, this statement flags as memory leak - - for( i = 0; i < NoOfFields; i++ ){ - if( GetFieldType( i ) == 'M' && MemoFieldExists( i )){ - Temp.PutLongField(i, 0L); - len = GetMemoFieldLen( i ); - if( len > BufSize ){ - if( Buf ) - free( Buf ); - if((Buf = (char *)malloc(len)) == NULL) - return XB_NO_MEMORY; - BufSize = len; - } - GetMemoField( i, len, Buf, -1 ); - Temp.UpdateMemoData( i, len, Buf, -1 ); - } - } -#endif - if(( rc = Temp.AppendRecord()) != XB_NO_ERROR ){ - if(Buf) free(Buf); - return rc; - } - } - } - if( Buf ) free( Buf ); - Temp.CloseDatabase(); - - if(fclose(fp) != 0) - return XB_CLOSE_ERROR; - - if(remove(GetFileName()) != 0) - return XB_WRITE_ERROR; - - if(rename(TempDbfName, GetFileName()) != 0) - return XB_WRITE_ERROR; - -#ifdef XB_MEMO_FIELDS - if( MemoFields ){ - if(fclose(mfp) != 0) - return XB_CLOSE_ERROR; - - if(remove(MemofileName) != 0) - return XB_WRITE_ERROR; - if( rename( TempDbtName, MemofileName ) != 0 ) - return XB_WRITE_ERROR; - if(( mfp = fopen( MemofileName, "r+b" )) == NULL ) - return XB_OPEN_ERROR; - if(( rc = GetDbtHeader(1)) != 0 ){ - fclose( mfp ); - return rc; - } -#ifdef XB_LOCKING_ON - /* no buffering in multi user mode */ - setbuf( mfp, NULL ); -#endif - } - -#endif /* XB_MEMO_FIELDS */ - - if(( fp = fopen( GetFileName(), "r+b" )) == NULL ) - return XB_OPEN_ERROR; - -#ifdef XB_LOCKING_ON - /* no buffering in multi user mode */ - setbuf( fp, NULL ); -#endif - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Pack the database -/*! - This method removes all records marked for deletion from an Xbase (.DBF) - file, reindexes any open index files, and also reorganizes any memo fields - stored in a .DBT memo file. - - \param packStatusFunc status function - \param indexStatusFunc index status function - - \param LockWaitOption One of the following: - \htmlonly - <p> - <table border=2><tr><th>LockWaitOption</th><th>Description</th></tr> - <tr><td>F_SETLK</td><td>Return immediately if the DBF file cannot be locked</td></tr> - <tr><td>XB_LOCK</td><td>Wait for lock on DBF file to succeed</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{LockWaitOption} & \textbf{Description} \\ \hline \hline - F\_SETLK & Return immediately if DBF file cannot be locked \\ \hline - F\_SETLKW & Wait for lock on DBF file to succeed \\ \hline - \end{tabular} - \endlatexonly - - \returns One of the following return codes: - \htmlonly - <p> - <table border=2><tr><th>Return Code</th><th>Description</th></tr> - <tr><td>XB_NO_ERROR</td><td>No error</td></tr> - <tr><td>XB_CLOSE_ERROR</td><td>Unable to close intermediate work file</td></tr> - <tr><td>XB_OPEN_ERROR</td><td>Could not open file</td></tr> - <tr><td>XB_NO_MEMORY</td><td>Memory allocation error</td></tr> - <tr><td>XB_WRITE_ERROR</td><td>Couldn't write to disk</td></tr> - <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> - <tr><td>XB_LOCK_FAILED</td><td>Unable to lock file or index</td></tr> - </table> - \endhtmlonly - \latexonly - \\ - \\ - \begin{tabular}{|l|l|} \hline - \textbf{Return Code} & \textbf{Description} \\ \hline \hline - XB\_NO\_ERROR & No Error \\ \hline - XB\_CLOSE\_ERROR & Unable to close intermediate work file \\ \hline - XB\_OPEN\_ERROR & Couldn't open the file \\ \hline - XB\_NO\_MEMORY & Memory allocation error \\ \hline - XB\_WRITE\_ERROR & Couldn't write to disk \\ \hline - XB\_SEEK\_ERROR & Error seeking file \\ \hline - XB\_LOCK\_FAILED & Unable to lock file or index \\ \hline - \end{tabular} - \endlatexonly -*/ -xbShort xbDbf::PackDatabase(xbShort LockWaitOption, - void (*packStatusFunc)(xbLong itemNum, xbLong numItems), - void (*indexStatusFunc)(xbLong itemNum, xbLong numItems)) -{ - xbShort rc; - - /* lock all open files and indexes */ -// if(( rc = ExclusiveLock( LockWaitOption )) != XB_NO_ERROR ) return rc; - - if(( rc = PackDatafiles(packStatusFunc)) != XB_NO_ERROR ){ -// ExclusiveUnlock(); - return rc; - } - - /* refresh file header */ - if(( rc = ReadHeader(1)) != XB_NO_ERROR ) - return rc; - - if(( rc = RebuildAllIndices(indexStatusFunc)) != XB_NO_ERROR ) - return rc; - -// ExclusiveUnlock(); - return XB_NO_ERROR; -} -/************************************************************************/ -//! Copy DBF structure -/*! -*/ -xbShort xbDbf::CopyDbfStructure(const char *NewFileName, xbShort Overlay) { - - xbShort rc, i; - xbString ndfn; /* new dbf file name */ - char ch; - -#ifdef XB_MEMO_FIELDS - char buf[9]; - xbShort ct, NameLen; - xbString MemoName; -#endif - FILE *t; - - /* build the new file name */ - rc = NameSuffixMissing( 1, NewFileName ); - ndfn = NewFileName; - if( rc == 1 ) - ndfn += ".dbf"; - else if( rc == 2 ) - ndfn += ".DBF"; - - /* check if the file exists and Overlay is on */ - if(((t = fopen( ndfn, "r" )) != NULL ) && !Overlay) { - fclose(t); - return XB_FILE_EXISTS; - } - - /* open new file */ - if((t = fopen(ndfn, "w+b")) == NULL) - return XB_OPEN_ERROR; - - /* copy the file header */ - if(( rc = _fseek( fp, 0, SEEK_SET )) != 0 ) - return XB_SEEK_ERROR; - - fputc( fgetc( fp ), t ); - - /* do the date */ - xbDate d; - ch = d.YearOf() - 1900; - if(XFV == 3) - ch %= 100; // dBASE III+ does this, dBASE IV does not. - fputc( ch, t ); - ch = d.MonthOf(); - fputc( ch, t ); - ch = d.DayOf( XB_FMT_MONTH ); - fputc( ch, t ); - - /* record count */ - for( i = 0; i < 4; i++ ) fputc( 0x00, t ); - - if((rc = _fseek(fp, 7, SEEK_CUR)) != 0) { - fclose( t ); - return XB_SEEK_ERROR; - } - for( i = 0; i < 4; i++ ) - fputc( fgetc( fp ), t ); - - for( i = 0; i < 17; i++ ) - fputc( 0x00, t ); - - if((rc = _fseek( fp, 17, SEEK_CUR )) != 0) { - fclose( t ); - return XB_SEEK_ERROR; - } - - for( i = 29; i < HeaderLen; i++ ) - fputc( fgetc( fp ), t ); - - fputc( 0x1a, t ); - fclose( t ); - -#ifdef XB_MEMO_FIELDS - if( MemoFieldsPresent()){ - MemoName = ndfn; - - NameLen = MemoName.len(); - NameLen--; - if( MemoName.getCharacter( NameLen ) == 'F' ) - MemoName.putAt(NameLen, 'T'); - else - MemoName.putAt(NameLen, 't'); - - if(( t = fopen( MemoName, "w+b" )) == NULL ) - return XB_OPEN_ERROR; - - memset( buf, 0x00, 4 ); - xbase->PutLong( buf, 1L ); - if(( fwrite( &buf, 4, 1, t )) != 1 ){ - fclose( t ); - return XB_WRITE_ERROR; - } - if( MemoHeader.Version == 0x03 ){ - for( i = 0; i < 12; i++ ) fputc( 0x00, t ); - fputc( 0x03, t ); - for( i = 0; i < 495; i++ ) fputc( 0x00, t ); - } - else - { - for( i = 0; i < 4; i++ ) fputc( 0x00, t ); // put 4 bytes 0x00 - memset( buf, 0x00, 9 ); - NameLen = ndfn.len(); - for( i = 0, ct = 0; i < NameLen; i++ ) - if( ndfn.getCharacter( i ) == PATH_SEPARATOR ){ - ct = i; - ct++; - } - - for( i = 0; i < 8 && ndfn[i+ct] != '.'; i++ ) - buf[i] = ndfn[i+ct]; - - fwrite( &buf, 8, 1, t ); - for( i = 0; i < 4; i++ ) fputc( 0x00, t ); - memset( buf, 0x00, 2 ); - xbase->PutShort( buf, MemoHeader.BlockSize ); - if(( fwrite( &buf, 2, 1, t )) != 1 ){ - fclose(t); - return XB_WRITE_ERROR; - } - for( i = 22; i < MemoHeader.BlockSize; i++ ) fputc( 0x00, t ); - } - } - fclose( t ); -#endif // XB_MEMO_FIELDS - return XB_NO_ERROR; -} -/************************************************************************/ -//! Add index to list -/*! - Adds the specified index to the list of indexes maintained by the - dbf. - - \param n index to add - \param IndexName name of index -*/ -#if defined(XB_INDEX_ANY) -xbShort xbDbf::AddIndexToIxList(xbIndex * n, const char *IndexName) -{ - xbIxList *i, *s, *t; - - if( !FreeIxList ){ - if((i = (xbIxList *) malloc(sizeof(xbIxList))) == NULL) - return XB_NO_MEMORY; - } - else - { - i = FreeIxList; - FreeIxList = i->NextIx; - } - memset(i, 0x00, sizeof(xbIxList)); - - i->IxName = IndexName; - i->index = n; - - s = NULL; - t = NdxList; - while( t && strcmp( t->IxName, IndexName ) < 0 ){ - s = t; - t = t->NextIx; - } - i->NextIx = t; - if( s == NULL ) - NdxList = i; - else - s->NextIx = i; - return 0; -} -#endif -/************************************************************************/ -//! Rebuild all index files -/*! -*/ -xbShort xbDbf::RebuildAllIndices(void (*statusFunc)(xbLong itemNum, xbLong numItems)) -{ -#if defined(XB_INDEX_ANY) - xbShort rc; - xbIxList *n; - - n = NdxList; - while( n ){ - if(( rc = n->index->ReIndex(statusFunc)) != XB_NO_ERROR ){ -// ExclusiveUnlock(); - return rc; - } - n = n->NextIx; - } -#endif - return XB_NO_ERROR; -} -/************************************************************************/ -//! Delete all records -/*! -*/ -xbShort xbDbf::DeleteAll( xbShort Option ) -{ - xbShort rc; - - if(( NoOfRecords()) == 0 ) - return XB_NO_ERROR; - if(( rc = GetFirstRecord()) != XB_NO_ERROR ) - return rc; - - if( Option == 0 ){ /* delete all option */ - while( 1 ){ - if( !RecordDeleted()) - if(( rc = DeleteRecord()) != XB_NO_ERROR ) - return rc; - if(( rc = GetNextRecord()) != XB_NO_ERROR ) - break; - } - } - else /* undelete all option */ - { - while( 1 ){ - if( RecordDeleted()) - if(( rc = UndeleteRecord()) != XB_NO_ERROR ) - return rc; - if(( rc = GetNextRecord()) != XB_NO_ERROR ) - break; - } - } - if( rc == XB_EOF ) - return XB_NO_ERROR; - else - return rc; -} -/************************************************************************/ -//! Delete all records and pack data file -/*! -*/ -xbShort xbDbf::Zap( xbShort WaitOption ) -{ - xbShort rc; - xbString TempDbfName, TempDbtName; - - CreateUniqueDbfName( TempDbfName, TempDbtName ); - if(( rc = CopyDbfStructure( TempDbfName, 1 )) != XB_NO_ERROR) { - return rc; - } - - if( fp ){ - fclose( fp ); - fp = 0; - } - - if(( rc = remove( GetFileName() )) != 0 ) - return XB_WRITE_ERROR; - - if(( rc = rename( TempDbfName, GetFileName() )) != 0 ) - return XB_WRITE_ERROR; - - if((fp = fopen( GetFileName(), "r+b" )) == NULL) - return XB_OPEN_ERROR; - -#ifdef XB_LOCKING_ON - setbuf( fp, NULL ); -#endif - ReadHeader( 1 ); - -#ifdef XB_MEMO_FIELDS - if( MemoFieldsPresent() ){ - fclose( mfp ); - - if(( rc = remove( MemofileName )) != 0 ) - return XB_WRITE_ERROR; - - if(( rc = rename( TempDbtName, MemofileName )) != 0 ) - return XB_WRITE_ERROR; - - if(( mfp = fopen( MemofileName, "r+b" )) == NULL) - return XB_OPEN_ERROR; - - } -#endif // XB_MEMO_FIELDS - - if(( rc = RebuildAllIndices()) != XB_NO_ERROR ) - return rc; - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Remove an index from the list -/*! -*/ -#if defined(XB_INDEX_ANY) -xbShort xbDbf::RemoveIndexFromIxList(xbIndex * n) { - xbIxList *i, *s; - - i = NdxList; - s = NULL; - while( i ){ - if( i->index == n ){ - /* remove it from current chain */ - if( s ) - s->NextIx = i->NextIx; - else - NdxList = i->NextIx; - - /* add i to the current free chain */ - i->NextIx = FreeIxList; - FreeIxList = i; - FreeIxList->IxName = (const char *)NULL; - FreeIxList->index = NULL; - break; - } - else - { - s = i; - i = i->NextIx; - } - } - return XB_NO_ERROR; -} -#endif - -/************************************************************************/ -//! Gets the number of records in the data file -/*! -*/ -xbLong xbDbf::NoOfRecords() -{ - xbLong numRecs; - -/* lock the database */ -#ifdef XB_LOCKING_ON - xbShort rc; - - if( AutoLock ){ -// if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR ) -// return rc; - - if((rc = ReadHeader(1)) != XB_NO_ERROR){ -// if(AutoLock) -// LockDatabase( XB_UNLOCK, 0L ); - return rc; - } - } -#endif - -#ifndef XB_REAL_DELETE - numRecs = NoOfRecs; -#else - numRecs = RealDelete ? RealNumRecs : NoOfRecs; -#endif - -#ifdef XB_LOCKING_ON -// if(AutoLock) -// LockDatabase( XB_UNLOCK, 0L ); -#endif - - return numRecs; -} -/************************************************************************/ -//! Get the physical number of records in the data file -/*! -*/ -xbLong xbDbf::PhysicalNoOfRecords() -{ - xbShort rc; - -/* lock the database */ -#ifdef XB_LOCKING_ON -// if( AutoLock ) -// if(( rc = LockDatabase( XB_LOCK, 0L )) != XB_NO_ERROR ) -// return rc; -#endif - - rc = ReadHeader(1); - -#ifdef XB_LOCKING_ON -// if(AutoLock) -// if(( rc = LockDatabase( XB_UNLOCK, 0L )) != XB_NO_ERROR ) -// return rc; -#endif - - if( rc ) - return rc; - - return NoOfRecs; -} - -/************************************************************************/ -#if defined(XB_INDEX_ANY) -//! Get the number of currently open indexes for data file -/*! -*/ -xbShort xbDbf::IndexCount() -{ - xbShort count; - xbIxList *i; - - for(count = 0, i = NdxList; i; i = i->NextIx, count++) ; - - return count; -} -/************************************************************************/ -//! Get a specific index -/*! -*/ -xbIndex * xbDbf::GetIndex(xbShort indexNum) -{ - xbIxList *i; - - i = NdxList; - while(indexNum && i){ - indexNum--; - i = i->NextIx; - } - - if(i) - return i->index; - - return 0; -} - -#endif // XB_INDEX_ANY -/************************************************************************/ -void xbDbf::Flush() -{ - if(fp) - fflush(fp); - -#ifdef XB_MEMO_FIELDS - if(mfp) - fflush(mfp); -#endif - -#if defined(XB_INDEX_ANY) - xbIxList - *i; - - i = NdxList; - while(i) { - i->index->Flush(); - i = i->NextIx; - } -#endif -} -/************************************************************************/ -#ifdef XB_LOCKING_ON -xbShort xbDbf::SetLockMode( xbShort nlm ) -{ -/* - xbShort rc; - if( LockMode != XB_XBASE_LOCK_MODE && - nlm == XB_XBASE_LOCK_MODE && - !xblfh ){ - rc = OpenXbLockFile(); - if( rc ) - return rc; - } -*/ - LockMode = nlm; - return XB_NO_ERROR; -} -#endif -/************************************************************************/ -const char * xbDbf::GetExtWithDot( bool lower ) -{ - return lower ? ".dbf" : ".DBF"; -} |