📄 dbf.cpp
字号:
/*************************************************************************** dbf.cpp - description ------------------- begin : Thu Jan 17 2002 copyright : (C) 2002 by email : ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* $Id: dbf.cpp,v 1.8 2001/02/20 17:54:15 dbryson Exp $ Xbase project source code This file contains the basic Xbase routines for reading and writing Xbase .DBF files. Copyright (C) 1997 StarTech, Gary A. Kunkel This library 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.1 of the License, or (at your option) any later version. This library 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Mail: Technology Associates, Inc. XBase Project 1455 Deming Way #11 Sparks, NV 89434 USA Email: xbase@techass.com See our website at: xdb.sourceforge.net V 1.0 10/10/97 - Initial release of software V 1.5 1/2/98 - Added memo field support V 1.6a 4/1/98 - Added expression support V 1.6b 4/8/98 - Numeric index keys V 1.6c 4/16/98 - Big Endian support, dBASE III + memo field support V 1.8 11/30/98 - Version 1.8 Upgrade V 1.9.2 9/14/99 - Fix to CreateDatabase - if field name too long Updated EOR and EOF processing V 1.9.2 4/16/2000 - fixed record locking logic in GetRecord reoutines - turned off buffering when locking is on V 1.9.2 6/14/2000 - Fixed Version header field to match empirical values for dBASE III+ and dBASE IV. V 1.9.2 6/15/2000 - Added call to InitVars() to cleanup error handling in CreateDatabase() and OpenDatabase().*/#ifdef __GNUG__ #pragma implementation "dbf.h"#endif#ifdef __WIN32__#include "xbconfigw32.h"#else#include "xbconfig.h"#endif#include "xbase.h"#ifdef HAVE_IO_H#include <io.h> #endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "xbexcept.h"/*! \file dbf.cpp*//************************************************************************///! Constructor/*! \param x pointer to the global xbXbase class*/xbDbf::xbDbf( xbXBase * x ){ xbase = x; InitVars();}/************************************************************************///! Initialize private data members./*! Internal use only.*/void xbDbf::InitVars( void ){ DatabaseName = (char)0x00; 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; MdxList = NULL; NdxList = NULL;// NtxList = NULL; FreeIxList = NULL; XFV = 3; /* Xbase file version */// strncpy(EofChar, "\x0D\x1A", 10);#ifdef XB_LOCKING_ON AutoLock = 1; CurLockType = -1; CurLockCount = 0; CurLockedRecNo = 0L; CurRecLockType = -1; CurRecLockCount = 0; CurMemoLockType = -1; CurMemoLockCount = 0;#else AutoLock = 0;#endif#ifdef XB_MEMO_FIELDS 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}/************************************************************************///! Calculate checksum for the current record./*! Internal use only.*/xbLong xbDbf::CalcCheckSum(){ xbShort i; char *p; p = RecBuf; xbLong l = 0L; for( i = 0; i < RecordLen; i++ ) l+= *p++; return l;}/************************************************************************///! 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; } xb_error(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( const xbShort PositionOption ){#if 0 char buf[4]; if (PositionOption) rewind( fp ); if(fwrite(&Version, 4, 1, fp) != 1) xb_error(XB_WRITE_ERROR); memset( buf, 0x00, 4 ); xbase->PutLong( buf, NoOfRecs ); if (fwrite(buf, 4, 1, fp) != 1) xb_error(XB_WRITE_ERROR); if (PositionOption == 2) return XB_NO_ERROR; memset( buf, 0x00, 4 ); xbase->PutShort( buf, HeaderLen ); if (fwrite(buf, 2, 1, fp) != 1) xb_error(XB_WRITE_ERROR); memset( buf, 0x00, 4 ); xbase->PutShort( buf, RecordLen ); if (fwrite(buf, 2, 1, fp) != 1) xb_error(XB_WRITE_ERROR); #ifdef XB_REAL_DELETE if(RealDelete) { memset(buf, 0x00, 4); xbase->PutULong(buf, FirstFreeRec); if (fwrite(buf, 4, 1, fp) != 1) xb_error(XB_WRITE_ERROR); memset(buf, 0x00, 4); xbase->PutULong(buf, RealNumRecs); if (fwrite(buf, 4, 1, fp) != 1) xb_error(XB_WRITE_ERROR); }#endif#else 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#endif if(fwrite(buf, 32, 1, fp) != 1) xb_error(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) xb_error(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 XDB 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 ){/* future release - add logic to check number of fields and record length */ xbShort i, j, k, k2, NameLen, rc, count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -