Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

1180 lines
20 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : DbfUtility.cpp
// = Version : ver2.0
// = Author : wlw
// = CreateDate : 2002-09-09
// = Description: Dbf工具类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
/*
Copyright?2002, Alexey Dolgachov
mail: alxsoft@gazinter.net
web: http://www.alxsoft.narod.ru
*/
#include "StdAfx.h"
#include "DbfUtility.h"
#include "TAString.h"
#include "TUString.h"
#include "TSqlCondition.h"
#include "TSqlQuiry.h"
#if ADS>15
#include <fstream>
#else
#include <fstream.H>
#endif
FieldInfo::FieldInfo(const TCHAR *n, int t, int l, int d)
{
InitClear();
if (n)
{
name = _strdup(_AS(n));
}
type = t;
len = l;
dec = d;
}
FieldInfo::FieldInfo(const FieldInfo &src)
{
InitClear();
*this = src;
}
FieldInfo::~FieldInfo()
{
if (name)
{
free(name);
}
}
FieldInfo& FieldInfo::operator= (const FieldInfo &src)
{
if (name)
{
free(name);
}
if (src.name)
{
name = _strdup(src.name);
}
else
{
name = NULL;
}
type = src.type;
len = src.len;
dec = src.dec;
return *this;
}
void FieldInfo::InitClear()
{
name = NULL;
type = 0;
len = 0;
dec = 0;
}
int FieldInfo::operator !()
{
return !name;
}
///////////////////////////////////////////////
// CodeBase -- Database classs
CodeBase::CodeBase()
{
d4init(this);
open_error = 0;
safety = 0;
auto_open = 0; // for auto open index
exclusive = 0;
read_only = 0;
read_lock = 0;
lock_attempts = -1;
}
CodeBase::~CodeBase()
{
d4close_all(this);
d4init_undo(this);
}
DbfTable * CodeBase::Open(const TCHAR *szFile)
{
TCHAR szShortPath[256] = _T("");
if (GetShortPathName(szFile, szShortPath, 256) == 0)
{
return NULL;
}
return(DbfTable *) d4open(this, _AS(szShortPath));
}
DbfTable * CodeBase::Create(const TCHAR *szFile, const FieldInfo *pFieldArray)
{
return (DbfTable *)d4create(this, (char *)_AS(szFile), (FIELD4INFO *)pFieldArray, NULL);
}
////////////////////////////////////////////////////////////
// Recordset class
DbfTable::DbfTable()
{
}
FieldInfo * DbfTable::GetFieldInfo()
{
return (FieldInfo *)d4field_info(this);
}
int DbfTable::GetFieldNum()
{
return d4num_fields(this);
}
FieldContent * DbfTable::GetFieldContent(const TCHAR *szFieldName)
{
return (FieldContent *)d4field(this, (char *)_AS(szFieldName));
}
// n=0, 1, 2, ..., base on ZERO
FieldContent * DbfTable::GetFieldContent(int n)
{
return (FieldContent *)d4field_j(this, n+1);
}
void DbfTable::Close()
{
d4close(this);
}
void DbfTable::AppendBegin()
{
d4append_start(this,0);
d4blank(this);
}
void DbfTable::AppendEnd()
{
d4append(this);
}
void DbfTable::Delete()
{
d4delete(this);
}
void DbfTable::Recall()
{
d4recall(this);
}
BOOL DbfTable::Pack()
{
return !d4pack(this);
}
// Iteration
int DbfTable::MoveFirst(int bSkipDeleted)
{
int nRet = (d4top(this) == 0 ? TRUE : FALSE);
if (IsDeleted() && bSkipDeleted)
{
nRet = MoveNext(bSkipDeleted);
}
return nRet;
}
int DbfTable::MoveLast(int bSkipDeleted)
{
int nRet = (d4bottom(this) == 0 ? TRUE : FALSE);
if (IsDeleted() && bSkipDeleted)
{
nRet = MovePrev(bSkipDeleted);
}
return nRet;
}
int DbfTable::MoveNext(int bSkipDeleted)
{
while (1)
{
d4skip(this, 1L);
if (IsEOF() || !bSkipDeleted)
{
break;
}
if (!IsDeleted())
{
break;
}
}
return (!IsEOF());
}
int DbfTable::MovePrev(int bSkipDeleted)
{
while(1)
{
d4skip(this, -1L);
if (IsBOF() || !bSkipDeleted)
{
break;
}
if (!IsDeleted())
{
break;
}
}
return (!IsBOF());
}
void DbfTable::Move(long offset, int bSkipDeleted)
{
if (offset)
{
long nStep = offset / abs(offset);
if (IsBOF() && offset > 0)
{
MoveFirst(bSkipDeleted);
offset--;
}
if (IsEOF() && offset < 0)
{
MoveLast(bSkipDeleted);
offset++;
}
for (long i = offset; i != 0L; i -= nStep)
{
if (nStep > 0)
{
MoveNext(bSkipDeleted);
}
else
{
MovePrev(bSkipDeleted);
}
}
}
}
int DbfTable::IsEOF()
{
return d4eof(this);
}
int DbfTable::IsBOF()
{
return d4bof(this);
}
int DbfTable::MoveTo(long nRecNo)
{
return (d4go(this, nRecNo + 1) == 0);
}
// Now, match method is not supported
int DbfTable::MoveTo(const TCHAR *szKey, const TCHAR *szValue, int nMethod, int bSkipDeleted)
{
for (MoveFirst(bSkipDeleted); !IsEOF(); MoveNext(bSkipDeleted))
{
TCString sValue;
GET_FIELD(this, szKey, sValue);
int bEqual = 0;
if (nMethod == CMP_SENSITIVE)
{
bEqual = (_tcscmp(szValue, sValue) == 0);
}
else
{
bEqual = (_tcsicmp(szValue, sValue) == 0);
}
if (bEqual)
{
return 1;
}
}
return 0;
}
int DbfTable::MoveFirst(const TCHAR *szKey, const TCHAR *szValue, int nMethod, int bSkipDeleted)
{
return MoveTo(szKey, szValue, nMethod, bSkipDeleted);
}
int DbfTable::MoveNext(const TCHAR *szKey, const TCHAR *szValue, int nMethod, int bSkipDeleted)
{
for (MoveNext(bSkipDeleted); !IsEOF(); MoveNext(bSkipDeleted))
{
TCString sValue;
GET_FIELD(this, szKey, sValue);
int bEqual = 0;
if (nMethod == CMP_SENSITIVE)
{
bEqual = (_tcscmp(szValue, sValue) == 0);
}
else
{
bEqual = (_tcsicmp(szValue, sValue) == 0);
}
if (bEqual)
{
return 1;
}
}
return 0;
}
long DbfTable::GetPosition()
{
return d4recno(this)-1;
}
int DbfTable::IsDeleted()
{
return d4deleted(this);
}
BOOL DbfTable::operator !()
{
return (IsEOF() || IsBOF());
}
int FieldContent::CompareTo(const FieldContent &otherOne) const
{
if (GetFieldType() != otherOne.GetFieldType())
{
return 0;
}
char cType = GetFieldType();
if (cType == r4num)
{
if (f4decimals((FIELD4 *)this) == 0)
{
int n1 = *this, n2 = otherOne;
if (n1 > n2)
{
return 1;
}
else if (n1 < n2)
{
return -1;
}
else
{
return 0;
}
}
else
{
double n1 = *this, n2 = otherOne;
if (n1 > n2)
{
return 1;
}
else if (n1 < n2)
{
return -1;
}
else
{
return 0;
}
}
}
else if (cType == r4str || cType == r4date || cType == r4log)
{
const TCHAR * s1 = *this, *s2 = otherOne;
return _tcscmp(s1, s2);
}
return 0;
}
// 求总记录数
long DbfTable::GetRecordCount(int bSkipDeleted)
{
if (!bSkipDeleted)
{
return d4reccount(this);
}
long lCount = 0;
for (MoveFirst(); !IsEOF(); MoveNext())
{
lCount ++;
}
return lCount;
}
void FieldInfo::ReleaseArray(FieldInfo *p)
{
u4free(p);
}
///////////////////////////////////////////////
// FieldContent
TCHAR FieldContent::szValue[256] = _T("");
FieldContent::FieldContent()
{
}
FieldContent::operator int () const
{
return f4int((FIELD4 *)this);
}
FieldContent::operator double () const
{
return f4double((FIELD4 *)this);
}
FieldContent::operator float () const
{
return (float)f4double((FIELD4 *)this);
}
FieldContent::operator const TCHAR * () const
{
#ifdef _UNICODE
char buf[256];
TGh1cpy(buf, f4str((FIELD4 *)this));
_tcscpy(szValue,TString(buf));
#else
TGh1cpy(szValue, f4str((FIELD4 *)this));
#endif
return (const TCHAR *)szValue;
}
char FieldContent::GetFieldType() const
{
return f4type((FIELD4 *)this);
}
FieldContent & FieldContent::operator = (int i)
{
f4assign_int(this, i);
return *this;
}
FieldContent & FieldContent::operator = (double d)
{
f4assign_double(this, d);
return *this;
}
FieldContent & FieldContent::operator = (const TCHAR *str)
{
f4assign(this, (char *)_AS(str));
return *this;
}
#ifdef __AFXDISP_H__
// 能正确正确转换的类型: int, double, string, date
COleVariant FieldContent::AsVariant() const
{
COleVariant res;
char cType=GetFieldType();
if (cType == r4num)
{
if (f4decimals((FIELD4 *)this) == 0)
{
res = (long)f4int((FIELD4 *)this);
}
else
{
res = f4double((FIELD4 *)this);
}
}
else if (cType == r4str)
{
const TCHAR* s1 = *this;
ASSERT(s1 != NULL);
res = s1;
}
else if (cType == r4log)
{
res = (long)f4int((FIELD4 *)this);
}
return res;
}
FieldContent & FieldContent::operator = (const COleVariant &src)
{
int nOleType = V_VT(&src);
switch(nOleType)
{
case VT_BSTR:
{
CString cs = V_BSTR(&src);
const TCHAR *sz = cs;
*this = sz;
}
break;
case VT_DATE:
{
COleDateTime oleDate = V_DATE(&src);
int nYear = oleDate.GetYear(),
nMonth = oleDate.GetMonth(),
nDay = oleDate.GetDay();
long nDate = nYear * 10000 + nMonth * 100 + nDay;
TCString sDate(_T("%ld"), nDate);
*this = sDate;
}
break;
case VT_I4:
{
long n1 = V_I4(&src);
*this = (int)n1;
}
break;
case VT_I2:
{
short n1 = V_I2(&src);
*this = (int)n1;
}
break;
case VT_R8:
{
double n1 = V_R8(&src);
*this = n1;
}
break;
case VT_R4:
{
float n1 = V_R4(&src);
*this = (double)n1;
}
break;
}
return *this;
}
int TARCH_IMPEXP CompareVariant(const COleVariant &var1, const COleVariant &var2)
{
int nType1 = V_VT(&var1), nType2 = V_VT(&var2);
int nRes = 0;
if (nType1 == nType2)
{
if (nType1 == VT_BSTR)
{
CString s1 = V_BSTR(&var1);
CString s2 = V_BSTR(&var2);
nRes = _tcscmp(s1, s2);
}
else if (nType1 == VT_DATE)
{
double d1 = V_DATE(&var1), d2 = V_DATE(&var2);
int nD1 = (int)d1, nD2 = (int)d2;
nRes = Compare(nD1, nD2);
}
else if (nType1 == VT_I4)
{
long n1 = V_I4(&var1), n2 = V_I4(&var2);
nRes = Compare(n1, n2);
}
else if (nType1 == VT_I2)
{
short n1 = V_I2(&var1), n2 = V_I2(&var2);
nRes = Compare(n1, n2);
}
else if (nType1 == VT_R8)
{
double n1 = V_R8(&var1), n2 = V_R8(&var2);
nRes = Compare(n1, n2);
}
else if (nType1 == VT_R4)
{
float n1 = V_R4(&var1), n2 = V_R4(&var2);
nRes = Compare(n1, n2);
}
}
return nRes;
}
// 比较两行的大小
int TARCH_IMPEXP CompareBookmark(COleVariant *g_lstSortFieldContents, const long *bookmark1, const long *bookmark2)
{
COleVariant &var1 = g_lstSortFieldContents[(int)(*bookmark1)],
&var2 = g_lstSortFieldContents[(int)(*bookmark2)];
return CompareVariant(var1, var2);
}
#endif
// 修改: 可以改多个记录
// 查询: 仅列出最后一个满足条件的记录
int
DBFFUN(DbfAccess &kz)
{
CodeBase code_base;
code_base.exclusive = (kz.flag == FLAG_PACK ? 1 : 0);
DATA4 *table = code_base.Open(kz.dbfname);
if (table == NULL)
{
return 1;
}
if (kz.flag == FLAG_PACK)
{
d4pack(table);
return 0;
}
FIELD4 *field;
int i,len;
char buf[150] = "", buf1[150] = "";
FILE *ftext = NULL;
int retFlag = 0;
int dbflen = d4num_fields(table);
// 由字段名换算字段序号
int *keyindex = kz.keynum > 0 ? new int [kz.keynum] : NULL; //如果不指定关键字则查询全部记录
int *dataindex = kz.datanum > 0 ? new int [kz.datanum] : NULL;
for (int k = 0; k < kz.keynum; k++)
{
if ((keyindex[k] = d4field_number(table, kz.keyFieldName[k])) <= 0)
{
return 1;
}
}
for (k = 0; k < kz.datanum; k++)
{
if ((dataindex[k] = d4field_number(table, kz.dataFieldName[k])) <= 0)
{
return 1;
}
}
int isExist = 0;
if (kz.flag == FLAG_READ || kz.flag == FLAG_WRITE || kz.flag == FLAG_DELETE) // read or modify
{
if (kz.flag == FLAG_READ)
{
if ((ftext = fopen(kz.resFileName,"w")) == NULL)
{
return 1;
}
}
for (d4top(table); !d4eof(table); d4skip(table, 1L))
{
if (d4deleted(table))
{
continue;
}
for (i = 0; i < kz.keynum; i++)
{
if (keyindex[i] > dbflen)
{
if (!kz.flag)
{
fclose(ftext);
}
return 1;
}
field = d4field_j(table,keyindex[i]);
// 局部比较, 当最后一字符为*时
int iLen = strlen(kz.keyinfo[i]);
int locCmp = (iLen >= 1 && kz.keyinfo[i][iLen - 1] == '*');
len = locCmp ? (iLen - 1) : f4len(field);
TGh3cpy(buf,kz.keyinfo[i],len);
TGh3cpy(buf1,f4str(field),len);
if (memcmp(buf,buf1,len))
{
break; //本行不满足查询条件
}
}
if (i == kz.keynum) // Find
{
isExist = 1;
if (kz.flag == FLAG_WRITE) // Write
{
for (i = 0; i < kz.datanum; i++)
{
if (dataindex[i] > dbflen)
{
exit(0);
}
field = d4field_j(table,dataindex[i]);
len = f4len(field);
TGh2cpy(buf,kz.dataIn[i],len);
if (f4type(field)==r4num && buf[0]) //数值型
{
double f = atof(buf);
f4assign_double(field,f);
}
else
{
f4assign(field,kz.dataIn[i]);
}
}
d4flush(table);
d4unlock(table);
}
else if (kz.flag == FLAG_READ) // Read
{
for (i = 0; i < kz.datanum; i++)
{
if (dataindex[i] > dbflen)
{
fclose(ftext);
exit(0);
}
field = d4field_j(table,dataindex[i]);
len = f4len(field);
TGh1cpy(buf,f4str(field));
fprintf(ftext,"\"%s\" ",buf);
}
fprintf(ftext,"\n");
}
else if (kz.flag == FLAG_DELETE)
{
d4delete(table);
}
}
}
if (ftext && kz.flag == FLAG_READ)
{
fclose(ftext);
}
}
if (kz.flag == FLAG_APPEND || (kz.flag == FLAG_WRITE && !isExist))
{
d4append_start(table,0);
d4blank(table);
for (i = 0; i < kz.datanum; i++)
{
if (dataindex[i] > dbflen)
{
exit(0);
}
field = d4field_j(table,dataindex[i]);
len = f4len(field);
TGh2cpy(buf,kz.dataIn[i],len);
if (f4type(field) == r4num && buf[0]) //数值型
{
double f = atof(buf);
f4assign_double(field,f);
}
else
{
f4assign(field,kz.dataIn[i]);
}
}
retFlag = d4append(table);
d4flush(table);
d4unlock(table);
}
if (keyindex)
{
delete keyindex;
}
if (dataindex)
{
delete dataindex;
}
return retFlag;
}
// keynum >=0 and datanum >0
DbfAccess:: DbfAccess(const TCHAR *tabName, int isWrite, int kn, int dn)
: flag(isWrite), keynum(kn), datanum(dn)
{
_tcscpy(dbfname, tabName);
if (keynum < 0 || datanum < 0)
{
exit(1);
}
keyFieldName = keynum > 0 ? new char * [keynum] : NULL;
keyinfo = keynum > 0 ? new char * [keynum] : NULL;
for (int i = 0; i < keynum; i++)
{
keyFieldName[i] = keyinfo[i] = NULL;
}
dataFieldName = datanum > 0 ? new char * [datanum] : NULL;
for (i = 0; i < datanum; i++)
{
dataFieldName[i] = NULL;
}
if (flag == FLAG_WRITE || flag == FLAG_APPEND) // write append
{
dataIn = new char * [datanum];
for (i = 0; i < datanum; i++)
{
dataIn[i] = NULL;
}
}
else
{
dataIn = NULL;
resFileName = NULL;
}
}
/******************* DbfAccess *****************/
DbfAccess:: ~DbfAccess()
{
for (int i = 0; i < keynum; i++)
{
if (keyFieldName[i])
{
free(keyFieldName[i]);
}
if (keyinfo[i])
{
free(keyinfo[i]);
}
}
if (keyFieldName)
{
delete[] keyFieldName;
}
if (keyinfo)
{
delete[] keyinfo;
}
for (i = 0; i < datanum; i++)
{
if (dataFieldName[i])
{
free(dataFieldName[i]);
}
if (dataFieldName)
{
delete[] dataFieldName;
}
if (flag == FLAG_WRITE || flag == FLAG_APPEND)
{
for (i = 0; i < datanum; i++)
{
if (dataIn[i])
{
free(dataIn[i]);
}
}
if (dataIn)
{
delete[] dataIn;
}
}
else if (flag == FLAG_READ)
{
if (resFileName)
{
free(resFileName);
}
}
}
}
unsigned _stklen = 30000U;
static int IsDigit(const char *str)
{
int len = strlen(str);
for (int i = 0; i < len; i++)
{
if (!isdigit(str[i]))
{
return 0;
}
}
return 1;
}
int operator == (TCStringList &strs1, TCStringList &strs2)
{
if (strs1.Length() != strs2.Length())
{
return 0;
}
int len = strs1.Length();
for (int i = 0; i<len; i++)
{
if (_tcscmp(strs1[i], strs2[i]) == 0)
{
;
}
else
{
return 0;
}
}
return 1;
}
// bugs: if sqlCmd is very long, output fileld more than 10, conditions field>=2
// syntax: SELECT [<output Fields>]/<*> FROM <dbf file> [<condition>]
// <condition> := WHERE <field name>=<value>
// value can't be empty, but can be ''(empty string)
int TARCH_IMPEXP SqlExec(const TCHAR *sqlcmd, const TCHAR *quiryOut, TDPtrList<TCStringList> *res)
{
if (!sqlcmd)
{
return 0;
}
TSqlQuiry cmd;
int i = 1;
int from = 0, where = 0;
TCString word(256);
while (GetStringAtIndex(sqlcmd, i, word))
{
if (i==1)
{
if (_tcsicmp(word, _T("SELECT")) != 0)
{
return 0;
}
}
else if (!from && _tcsicmp(word, _T("from")) == 0)
{
from = 1;
}
else if (!where && _tcsicmp(word, _T("where")) == 0)
{
where = 1;
}
else
{
if (!from) // Specify OutPut field
{
if (_tcsicmp(word, _T("DISTINCT")) == 0)
{
cmd.isDistinct = 1;
}
else
{
cmd.outputFields.Append(tstrnew(word));
}
}
else
{
if (!where && !cmd.dbfFile)
{
cmd.dbfFile = word;
}
else if (where) // Condtion is here
{
const char *pstr;
char fieldKey[80] = "", fieldValue[256] = "";
DataCompare cp;
TAString aword(word);
if ((pstr = strstr(aword, ">=")))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+2);
cp = GREAT_EQUAL;
}
else if ((pstr = strchr(aword, '>')))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+1);
cp = GREAT;
}
else if ((pstr = strstr(aword, "<=")))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+2);
cp = LITTLE_EQUAL;
}
else if ((pstr = strchr(aword, '<')))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+1);
cp = LITTLE;
}
else if ((pstr = strstr(aword, "!=")))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+2);
cp = NOT_EQUAL;
}
else if ((pstr = strchr(aword, '=')))
{
int n = 0;
for (const char *p = aword; p != pstr; p++, n++)
{
fieldKey[n] = *p;
}
fieldKey[n] = 0;
strcpy(fieldValue, p+1);
cp = EQUAL;
}
else
{
return 0;
}
if (!fieldKey[0] || !fieldValue[0])
{
return 0;
}
TSqlCondition *condPtr = new TSqlCondition;
condPtr->fieldName = fieldKey;
condPtr->opr = cp;
int nLen = strlen(fieldValue);
if (fieldValue[0] == '\'' && nLen > 1 && fieldValue[nLen-1] == '\'')
{
condPtr->type = SQL_CHAR;
char str[256];
strcpy(str, &fieldValue[1]);
str[strlen(str) - 1] = 0;
condPtr->rstring = _strdup(str);
}
else if (IsDigit(fieldValue))
{
condPtr->type = SQL_INT;
condPtr->rint = atoi(fieldValue);
}
else if (strchr(fieldValue, '.'))
{
condPtr->type = SQL_REAL;
condPtr->rreal= atof(fieldValue);
}
else
{
condPtr->type = SQL_CHAR;
condPtr->rstring = _strdup(fieldValue);
}
cmd.conditions.Append(condPtr);
}
}
}
i++;
}
if (cmd.Execute())
{
if (quiryOut)
{
#if (ADS > 15)
std::
#endif
ofstream fileOut(quiryOut);
cmd.QuiryOut(fileOut);
}
if (res)
{
res->Reset();
int len = cmd.outbuf.Length();
for (int k = 0; k < len; k++)
{
TCStringList *strList = new TCStringList;
*strList = *cmd.outbuf[k];
res->Append(strList);
}
}
return 1;
}
else
{
}
return 0;
}