From 268c9d28dc3326a87aaa9c702ecb41f54771c080 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Tue, 30 May 2006 10:28:42 +0000 Subject: [PATCH] 2006-05-30 12:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbver.h * changed version number and ChangeLog entry * harbour/make_tgz.sh ! fixed creating PP in DJGPP builds * harbour/contrib/dot/pp.prg ! minor fix in parameter checking * harbour/contrib/libmisc/hb_f.c ! fixed bug in record numbering after reaching EOF position and backward skipping * harbour/include/hbrdddel.h * harbour/source/rdd/delim1.c + implemented DELIM RDD. It should be fully Clipper compatible in comma files parsing. If you will find any difference, please inform me and I'll update it. Unlike in Clipper in [x]Harbour these RDD can be used also in direct import operations with APPEND FROM ... VIA "DELIM" These RDD also support whole record transfering between RDDs if they support the same record format and field representation and can translate extended field types like "I", "B", "V3", "V4", etc. * harbour/source/rtl/dbdelim.prg * replaced old code of __dbDelim() function with simple calls to __dbCopy()/__dbApp() - it should fix most of the reported incompatibilities in DELIM import/export operations and increase their speed many times * harbour/include/hbrddsdf.h * harbour/source/rdd/sdf1.c + implemented SDF RDD. It should be fully Clipper compatible in SDF files parsing. If you will find any difference, please inform me and I'll update it. Unlike in Clipper in [x]Harbour these RDD can be used also in direct import operations with APPEND FROM ... VIA "SDF" These RDD also support whole record transfering between RDDs if they support the same record format and field representation and can translate extended field types like "I", "B", "V3", "V4", etc. * harbour/source/rtl/dbsdf.prg * replaced old code of __dbSDF() function with simple calls to __dbCopy()/__dbApp() - it should fix most of the reported incompatibilities in SDF import/export operations and increase their speed many times * harbour/source/rdd/dbcmd.c + added support for table structure inheriting in transfer RDDs. + added eleventh parameter with delimiter to __dbCopy()/__dbApp() * harbour/source/rdd/dbf1.c * force 10 bytes size for memo fields in DBF and SMT memos. * some minor clean-up. * harbour/source/rdd/workarea.c * added some dummy DBI_* actions in base RDD level --- harbour/ChangeLog | 61 ++ harbour/contrib/dot/pp.prg | 2 +- harbour/contrib/libmisc/hb_f.c | 8 +- harbour/include/hbrdddel.h | 179 ++-- harbour/include/hbrddsdf.h | 171 ++-- harbour/include/hbver.h | 6 +- harbour/make_tgz.sh | 13 +- harbour/source/rdd/dbcmd.c | 114 ++- harbour/source/rdd/dbf1.c | 40 +- harbour/source/rdd/delim1.c | 1497 +++++++++++++++++++++++++++++--- harbour/source/rdd/sdf1.c | 1266 ++++++++++++++++++++++++--- harbour/source/rdd/workarea.c | 21 +- harbour/source/rtl/dbdelim.prg | 21 + harbour/source/rtl/dbsdf.prg | 20 + 14 files changed, 2948 insertions(+), 471 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d9d2ebeb7a..a2d6626a45 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,67 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2006-05-31 13:45 UTC+0200 Tomaz Zupan (tomaz.zupan at orpo.si) + * harbour.spec + * Added Mandriva to recognised distros + * Sinchronised version with harbour/include/hbver.h + +2006-05-30 18:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rdd/sdf1.c + * cleaned BCC warning + * harbour/source/rdd/delim1.c + ! fixed BCC compilation (string initialization with dynamic + values is forbidden by BCC) + +2006-05-30 12:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbver.h + * changed version number and ChangeLog entry + + * harbour/make_tgz.sh + ! fixed creating PP in DJGPP builds + + * harbour/contrib/dot/pp.prg + ! minor fix in parameter checking + + * harbour/contrib/libmisc/hb_f.c + ! fixed bug in record numbering after reaching EOF position and + backward skipping + + * harbour/include/hbrdddel.h + * harbour/source/rdd/delim1.c + + implemented DELIM RDD. It should be fully Clipper compatible + in comma files parsing. If you will find any difference, please + inform me and I'll update it. Unlike in Clipper in [x]Harbour + these RDD can be used also in direct import operations with + APPEND FROM ... VIA "DELIM" + These RDD also support whole record transfering between RDDs + if they support the same record format and field representation + and can translate extended field types like "I", "B", "V3", "V4", + etc. + + * harbour/source/rtl/dbdelim.prg + * replaced old code of __dbDelim() function with simple calls to + __dbCopy()/__dbApp() - it should fix most of the reported + incompatibilities in DELIM import/export operations and + increase their speed many times + + * harbour/include/hbrddsdf.h + * harbour/source/rdd/sdf1.c + + implemented SDF RDD. It should be fully Clipper compatible + in SDF files parsing. If you will find any difference, please + inform me and I'll update it. Unlike in Clipper in [x]Harbour + these RDD can be used also in direct import operations with + APPEND FROM ... VIA "SDF" + These RDD also support whole record transfering between RDDs + if they support the same record format and field representation + and can translate extended field types like "I", "B", "V3", "V4", + etc. + + * harbour/source/rtl/dbsdf.prg + * replaced old code of __dbSDF() function with simple calls to + __dbCopy()/__dbApp() - it should fix most of the reported + incompatibilities in SDF import/export operations and + increase their speed many times * harbour/source/rdd/dbcmd.c + added support for table structure inheriting in transfer RDDs. diff --git a/harbour/contrib/dot/pp.prg b/harbour/contrib/dot/pp.prg index c42161ea1d..beb1827bc7 100644 --- a/harbour/contrib/dot/pp.prg +++ b/harbour/contrib/dot/pp.prg @@ -439,7 +439,7 @@ STATIC s_aSwitchDefs := {} bCompile := .T. sSwitch := "" aParams := { p1, p2, p3, p4, p5, p6, p7, p8, p9 } - aSize( aParams, PCount() ) + aSize( aParams, PCount() - 1 ) endif #endif diff --git a/harbour/contrib/libmisc/hb_f.c b/harbour/contrib/libmisc/hb_f.c index 4b8bafc5af..2a9d81de7e 100644 --- a/harbour/contrib/libmisc/hb_f.c +++ b/harbour/contrib/libmisc/hb_f.c @@ -253,7 +253,7 @@ HB_FUNC( HB_FGOBOTTOM ) { int x; int len; - long loc; + long loc, last; if ( last_rec[area] != 0 ) { recno[area] = last_rec[area]; @@ -263,14 +263,15 @@ HB_FUNC( HB_FGOBOTTOM ) loc = 0L; + last = offset[area]; do { - hb_fsSeek( handles[area], offset[area], SEEK_SET ); len = hb_fsRead( handles[area], ( BYTE * ) c, c_size ); for ( x = 0; x < len; x++ ) { if ( ((*(c + x) == 13) && (*(c + x + 1) == 10)) || ((*(c + x) == 10) && (*(c + x + 1) == 13)) || ( x - loc > b_size ) ) { + last = offset[area] + loc; recno[area]++; x++; loc = x + 1; @@ -281,7 +282,7 @@ HB_FUNC( HB_FGOBOTTOM ) } while ( len == c_size ); last_rec[area] = --recno[area]; - last_off[area] = offset[area]; + last_off[area] = last; } } @@ -371,6 +372,7 @@ HB_FUNC( HB_FREADANDSKIP ) ((*(b + x) == 10) && x < read-1 && (*(b + x + 1) == 13)) ) { x += 2; + bHasCRLF = TRUE; break; } x++; diff --git a/harbour/include/hbrdddel.h b/harbour/include/hbrdddel.h index 5ca2bb7655..80599fb882 100644 --- a/harbour/include/hbrdddel.h +++ b/harbour/include/hbrdddel.h @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * DELIMITED RDD module + * DELIM RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -57,109 +57,84 @@ HB_EXTERN_BEGIN +/* DELIMITED default file extensions */ +#define DELIM_TABLEEXT ".txt" + + /* - * -- DELIMITED METHODS -- + * DELIM WORKAREA + * ------------ + * The Workarea Structure of DELIM RDD + * */ -#define hb_delimBof NULL -#define hb_delimEof NULL -#define hb_delimFound NULL -#define hb_delimGoBottom NULL -#define hb_delimGoTo NULL -#define hb_delimGoToId NULL -#define hb_delimGoTop NULL -#define hb_delimSeek NULL -#define hb_delimSkip NULL -#define hb_delimSkipFilter NULL -#define hb_delimSkipRaw NULL -#define hb_delimAddField NULL -#define hb_delimAppend NULL -#define hb_delimCreateFields NULL -#define hb_delimDeleteRec NULL -#define hb_delimDeleted NULL -#define hb_delimFieldCount NULL -#define hb_delimFieldDisplay NULL -#define hb_delimFieldInfo NULL -#define hb_delimFieldName NULL -#define hb_delimFlush NULL -#define hb_delimGetRec NULL -#define hb_delimGetValue NULL -#define hb_delimGetVarLen NULL -#define hb_delimGoCold NULL -#define hb_delimGoHot NULL -#define hb_delimPutRec NULL -#define hb_delimPutValue NULL -#define hb_delimRecall NULL -#define hb_delimRecCount NULL -#define hb_delimRecInfo NULL -#define hb_delimRecNo NULL -#define hb_delimRecId NULL -#define hb_delimSetFieldExtent NULL -#define hb_delimAlias NULL -#define hb_delimClose NULL -#define hb_delimCreate NULL -#define hb_delimInfo NULL -#define hb_delimNewArea NULL -#define hb_delimOpen NULL -#define hb_delimRelease NULL -#define hb_delimStructSize NULL -#define hb_delimSysName NULL -#define hb_delimEval NULL -#define hb_delimPack NULL -#define hb_delimPackRec NULL -#define hb_delimSort NULL -#define hb_delimTrans NULL -#define hb_delimTransRec NULL -#define hb_delimZap NULL -#define hb_delimChildEnd NULL -#define hb_delimChildStart NULL -#define hb_delimChildSync NULL -#define hb_delimSyncChildren NULL -#define hb_delimClearRel NULL -#define hb_delimForceRel NULL -#define hb_delimRelArea NULL -#define hb_delimRelEval NULL -#define hb_delimRelText NULL -#define hb_delimSetRel NULL -#define hb_delimOrderListAdd NULL -#define hb_delimOrderListClear NULL -#define hb_delimOrderListDelete NULL -#define hb_delimOrderListFocus NULL -#define hb_delimOrderListRebuild NULL -#define hb_delimOrderCondition NULL -#define hb_delimOrderCreate NULL -#define hb_delimOrderDestroy NULL -#define hb_delimOrderInfo NULL -#define hb_delimClearFilter NULL -#define hb_delimClearLocate NULL -#define hb_delimClearScope NULL -#define hb_delimCountScope NULL -#define hb_delimFilterText NULL -#define hb_delimScopeInfo NULL -#define hb_delimSetFilter NULL -#define hb_delimSetLocate NULL -#define hb_delimSetScope NULL -#define hb_delimSkipScope NULL -#define hb_delimLocate NULL -#define hb_delimCompile NULL -#define hb_delimError NULL -#define hb_delimEvalBlock NULL -#define hb_delimRawLock NULL -#define hb_delimLock NULL -#define hb_delimUnLock NULL -#define hb_delimCloseMemFile NULL -#define hb_delimCreateMemFile NULL -#define hb_delimGetValueFile NULL -#define hb_delimOpenMemFile NULL -#define hb_delimPutValueFile NULL -#define hb_delimReadDBHeader NULL -#define hb_delimWriteDBHeader NULL -#define hb_delimInit NULL -#define hb_delimExit NULL -#define hb_delimDrop NULL -#define hb_delimExists NULL -#define hb_delimRddInfo NULL -#define hb_delimWhoCares NULL +typedef struct _DELIMAREA +{ + struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ + USHORT uiArea; /* The number assigned to this workarea */ + void * atomAlias; /* Pointer to the alias symbol for this workarea */ + USHORT uiFieldExtent; /* Total number of fields allocated */ + USHORT uiFieldCount; /* Total number of fields used */ + LPFIELD lpFields; /* Pointer to an array of fields */ + void * lpFieldExtents; /* Void ptr for additional field properties */ + PHB_ITEM valResult; /* All purpose result holder */ + BOOL fTop; /* TRUE if "top" */ + BOOL fBottom; /* TRUE if "bottom" */ + BOOL fBof; /* TRUE if "bof" */ + BOOL fEof; /* TRUE if "eof" */ + BOOL fFound; /* TRUE if "found" */ + DBSCOPEINFO dbsi; /* Info regarding last LOCATE */ + DBFILTERINFO dbfi; /* Filter in effect */ + LPDBORDERCONDINFO lpdbOrdCondInfo; + LPDBRELINFO lpdbRelations; /* Parent/Child relationships used */ + USHORT uiParents; /* Number of parents for this area */ + USHORT heap; + USHORT heapSize; + USHORT rddID; + USHORT uiMaxFieldNameLength; + PHB_CODEPAGE cdPage; /* Area's codepage pointer */ + + /* + * DELIM's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + FHANDLE hFile; /* Data file handle */ + char * szFileName; /* Name of data file */ + char * szEol; /* EOL marker */ + USHORT uiEolLen; /* Size of EOL marker */ + BOOL fDelim; /* Use character field delimiter? */ + char cDelim; /* Character field delimiter */ + char cSeparator; /* Field delimiter */ + USHORT uiRecordLen; /* Size of record */ + USHORT * pFieldOffset; /* Pointer to field offset array */ + BYTE * pRecord; /* Buffer of record data */ + BYTE * pBuffer; /* Read/Write */ + ULONG ulBufferSize; /* IO buffer size */ + ULONG ulBufferRead; /* Number of bytes in read buffer */ + ULONG ulBufferIndex; /* Index to read read buffer */ + HB_FOFFSET ulRecordOffset; /* Current record offest */ + HB_FOFFSET ulNextOffset; /* Next record offest */ + HB_FOFFSET ulFileSize; /* File table size in export mode */ + HB_FOFFSET ulBufferStart; /* Start offset of read buffer */ + ULONG ulRecNo; /* Current record */ + ULONG ulRecCount; /* Number of records (in export) */ + BOOL fTransRec; /* Can put whole records */ + BOOL fFlush; /* Data was written to table and not commited */ + BOOL fShared; /* Shared file */ + BOOL fReadonly; /* Read only file */ + BOOL fPositioned; /* Positioned record */ + BOOL fRecordChanged; /* Record changed */ +} DELIMAREA; + +typedef DELIMAREA * LPDELIMAREA; + +#ifndef DELIMAREAP +#define DELIMAREAP LPDELIMAREA +#endif HB_EXTERN_END diff --git a/harbour/include/hbrddsdf.h b/harbour/include/hbrddsdf.h index d1cebbf81a..3489d502f5 100644 --- a/harbour/include/hbrddsdf.h +++ b/harbour/include/hbrddsdf.h @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * SDF RDD module + * SDF RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -57,109 +57,76 @@ HB_EXTERN_BEGIN +/* SDF default file extensions */ +#define SDF_TABLEEXT ".txt" + + /* - * -- SDF METHODS -- + * SDF WORKAREA + * ------------ + * The Workarea Structure of SDF RDD + * */ -#define hb_sdfBof NULL -#define hb_sdfEof NULL -#define hb_sdfFound NULL -#define hb_sdfGoBottom NULL -#define hb_sdfGoTo NULL -#define hb_sdfGoToId NULL -#define hb_sdfGoTop NULL -#define hb_sdfSeek NULL -#define hb_sdfSkip NULL -#define hb_sdfSkipFilter NULL -#define hb_sdfSkipRaw NULL -#define hb_sdfAddField NULL -#define hb_sdfAppend NULL -#define hb_sdfCreateFields NULL -#define hb_sdfDeleteRec NULL -#define hb_sdfDeleted NULL -#define hb_sdfFieldCount NULL -#define hb_sdfFieldDisplay NULL -#define hb_sdfFieldInfo NULL -#define hb_sdfFieldName NULL -#define hb_sdfFlush NULL -#define hb_sdfGetRec NULL -#define hb_sdfGetValue NULL -#define hb_sdfGetVarLen NULL -#define hb_sdfGoCold NULL -#define hb_sdfGoHot NULL -#define hb_sdfPutRec NULL -#define hb_sdfPutValue NULL -#define hb_sdfRecall NULL -#define hb_sdfRecCount NULL -#define hb_sdfRecInfo NULL -#define hb_sdfRecNo NULL -#define hb_sdfRecId NULL -#define hb_sdfSetFieldExtent NULL -#define hb_sdfAlias NULL -#define hb_sdfClose NULL -#define hb_sdfCreate NULL -#define hb_sdfInfo NULL -#define hb_sdfNewArea NULL -#define hb_sdfOpen NULL -#define hb_sdfRelease NULL -#define hb_sdfStructSize NULL -#define hb_sdfSysName NULL -#define hb_sdfEval NULL -#define hb_sdfPack NULL -#define hb_sdfPackRec NULL -#define hb_sdfSort NULL -#define hb_sdfTrans NULL -#define hb_sdfTransRec NULL -#define hb_sdfZap NULL -#define hb_sdfChildEnd NULL -#define hb_sdfChildStart NULL -#define hb_sdfChildSync NULL -#define hb_sdfSyncChildren NULL -#define hb_sdfClearRel NULL -#define hb_sdfForceRel NULL -#define hb_sdfRelArea NULL -#define hb_sdfRelEval NULL -#define hb_sdfRelText NULL -#define hb_sdfSetRel NULL -#define hb_sdfOrderListAdd NULL -#define hb_sdfOrderListClear NULL -#define hb_sdfOrderListDelete NULL -#define hb_sdfOrderListFocus NULL -#define hb_sdfOrderListRebuild NULL -#define hb_sdfOrderCondition NULL -#define hb_sdfOrderCreate NULL -#define hb_sdfOrderDestroy NULL -#define hb_sdfOrderInfo NULL -#define hb_sdfClearFilter NULL -#define hb_sdfClearLocate NULL -#define hb_sdfClearScope NULL -#define hb_sdfCountScope NULL -#define hb_sdfFilterText NULL -#define hb_sdfScopeInfo NULL -#define hb_sdfSetFilter NULL -#define hb_sdfSetLocate NULL -#define hb_sdfSetScope NULL -#define hb_sdfSkipScope NULL -#define hb_sdfLocate NULL -#define hb_sdfCompile NULL -#define hb_sdfError NULL -#define hb_sdfEvalBlock NULL -#define hb_sdfRawLock NULL -#define hb_sdfLock NULL -#define hb_sdfUnLock NULL -#define hb_sdfCloseMemFile NULL -#define hb_sdfCreateMemFile NULL -#define hb_sdfGetValueFile NULL -#define hb_sdfOpenMemFile NULL -#define hb_sdfPutValueFile NULL -#define hb_sdfReadDBHeader NULL -#define hb_sdfWriteDBHeader NULL -#define hb_sdfInit NULL -#define hb_sdfExit NULL -#define hb_sdfDrop NULL -#define hb_sdfExists NULL -#define hb_sdfRddInfo NULL -#define hb_sdfWhoCares NULL +typedef struct _SDFAREA +{ + struct _RDDFUNCS * lprfsHost; /* Virtual method table for this workarea */ + USHORT uiArea; /* The number assigned to this workarea */ + void * atomAlias; /* Pointer to the alias symbol for this workarea */ + USHORT uiFieldExtent; /* Total number of fields allocated */ + USHORT uiFieldCount; /* Total number of fields used */ + LPFIELD lpFields; /* Pointer to an array of fields */ + void * lpFieldExtents; /* Void ptr for additional field properties */ + PHB_ITEM valResult; /* All purpose result holder */ + BOOL fTop; /* TRUE if "top" */ + BOOL fBottom; /* TRUE if "bottom" */ + BOOL fBof; /* TRUE if "bof" */ + BOOL fEof; /* TRUE if "eof" */ + BOOL fFound; /* TRUE if "found" */ + DBSCOPEINFO dbsi; /* Info regarding last LOCATE */ + DBFILTERINFO dbfi; /* Filter in effect */ + LPDBORDERCONDINFO lpdbOrdCondInfo; + LPDBRELINFO lpdbRelations; /* Parent/Child relationships used */ + USHORT uiParents; /* Number of parents for this area */ + USHORT heap; + USHORT heapSize; + USHORT rddID; + USHORT uiMaxFieldNameLength; + PHB_CODEPAGE cdPage; /* Area's codepage pointer */ + + /* + * SDFS's additions to the workarea structure + * + * Warning: The above section MUST match WORKAREA exactly! Any + * additions to the structure MUST be added below, as in this + * example. + */ + + FHANDLE hFile; /* Data file handle */ + char * szFileName; /* Name of data file */ + char * szEol; /* EOL marker */ + USHORT uiEolLen; /* Size of EOL marker */ + USHORT uiRecordLen; /* Size of record */ + USHORT * pFieldOffset; /* Pointer to field offset array */ + BYTE * pRecord; /* Buffer of record data */ + HB_FOFFSET ulRecordOffset; /* Current record offest */ + HB_FOFFSET ulNextOffset; /* Next record offest */ + HB_FOFFSET ulFileSize; /* File table size in export mode */ + ULONG ulRecNo; /* Current record */ + ULONG ulRecCount; /* Number of records (in export) */ + BOOL fTransRec; /* Can put whole records */ + BOOL fFlush; /* Data was written to SDF and not commited */ + BOOL fShared; /* Shared file */ + BOOL fReadonly; /* Read only file */ + BOOL fPositioned; /* Positioned record */ + BOOL fRecordChanged; /* Record changed */ +} SDFAREA; + +typedef SDFAREA * LPSDFAREA; + +#ifndef SDFAREAP +#define SDFAREAP LPSDFAREA +#endif HB_EXTERN_END diff --git a/harbour/include/hbver.h b/harbour/include/hbver.h index 2c8f514147..d5727975f1 100644 --- a/harbour/include/hbver.h +++ b/harbour/include/hbver.h @@ -62,13 +62,13 @@ /* NOTE: One of these next three fields can be incremented by the hbverfix program */ #define HB_VER_MAJOR 0 /* Major version number */ -#define HB_VER_MINOR 46 /* Minor version number */ +#define HB_VER_MINOR 47 /* Minor version number */ #define HB_VER_REVISION 0 /* Revision number */ /* NOTE: The next two fields are automatically updated by the hbverfix program */ -#define HB_VER_LENTRY "2006-05-29 14:10 UTC+0100 Ryszard Glab" -#define HB_VER_CHLCVS "ChangeLog,v 1.4894 2006/05/29 11:59:37 rglab" +#define HB_VER_LENTRY "2006-05-30 12:09 UTC+0300 Chen Kedem" +#define HB_VER_CHLCVS "ChangeLog,v 1.4896 2006/05/30 09:09:16 ckedem" /* TOFIX: The next three fields need to get updated automatically */ diff --git a/harbour/make_tgz.sh b/harbour/make_tgz.sh index db0ee71f09..b4106940ab 100644 --- a/harbour/make_tgz.sh +++ b/harbour/make_tgz.sh @@ -255,13 +255,14 @@ then fi # Create and install PP -pushd contrib/dot -$HB_BIN_INSTALL/${hb_pref}mk pp -n -w -D_DEFAULT_INC_DIR=\"${_DEFAULT_INC_DIR}\" -$INSTALL -m755 pp $HB_BIN_INSTALL/pp -ln -s pp $HB_BIN_INSTALL/pprun +(cd contrib/dot +export PRG_USR="\"-D_DEFAULT_INC_DIR='${_DEFAULT_INC_DIR}'\"" +$HB_BIN_INSTALL/${hb_pref}mk pp -n -w +strip pp${hb_exesuf} +$INSTALL -m755 pp${hb_exesuf} $HB_BIN_INSTALL/pp${hb_exesuf} +ln -s pp${hb_exesuf} $HB_BIN_INSTALL/pprun${hb_exesuf} $INSTALL -m644 rp_dot.ch $HB_INC_INSTALL/ -rm -f pp -popd +rm -f pp${hb_exesuf}) CURDIR=$(pwd) diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index f76083119d..09c7658f28 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -75,6 +75,7 @@ #include "hbapilng.h" #include "hbapiitm.h" #include "hbrddwrk.h" +#include "rddsys.ch" #if defined(__XHARBOUR__) #include "hbfast.h" #else @@ -1589,7 +1590,8 @@ HB_FUNC( DBCOMMITALL ) static ERRCODE hb_rddOpenTable( char * szFileName, char * szDriver, USHORT uiArea, char *szAlias, BOOL fShared, BOOL fReadonly, - char * szCpId, ULONG ulConnection ) + char * szCpId, ULONG ulConnection, + PHB_ITEM pStruct ) { char szDriverBuffer[ HARBOUR_MAX_RDD_DRIVERNAME_LENGTH + 1 ]; DBOPENINFO pInfo; @@ -1642,13 +1644,25 @@ static ERRCODE hb_rddOpenTable( char * szFileName, char * szDriver, pInfo.ulConnection = ulConnection; pInfo.lpdbHeader = NULL; - /* Open file */ - errCode = SELF_OPEN( pArea, &pInfo ); - - if( errCode != SUCCESS ) + if( pStruct ) { - hb_rddReleaseCurrentArea(); - hb_rddSelectWorkAreaNumber( uiPrevArea ); + errCode = SELF_CREATEFIELDS( pArea, pStruct ); + } + else + { + errCode = SUCCESS; + } + + if( errCode == SUCCESS ) + { + /* Open file */ + errCode = SELF_OPEN( pArea, &pInfo ); + + if( errCode != SUCCESS ) + { + hb_rddReleaseCurrentArea(); + hb_rddSelectWorkAreaNumber( uiPrevArea ); + } } s_bNetError = errCode != SUCCESS; @@ -2247,7 +2261,7 @@ HB_FUNC( DBUSEAREA ) hb_parl( 1 ) ? 0 : hb_rddGetCurrentWorkAreaNumber(), hb_parc( 4 ), ISLOG( 5 ) ? hb_parl( 5 ) : !hb_set.HB_SET_EXCLUSIVE, - hb_parl( 6 ), hb_parc( 7 ), hb_parnl( 8 ) ); + hb_parl( 6 ), hb_parc( 7 ), hb_parnl( 8 ), NULL ); } HB_FUNC( __DBZAP ) @@ -4282,11 +4296,13 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, PHB_ITEM pCobWhile, PHB_ITEM pStrWhile, PHB_ITEM pNext, PHB_ITEM pRecID, PHB_ITEM pRest, - char *szCpId ) + char *szCpId, + PHB_ITEM pDelim ) { - AREAP lpaSource, lpaDest, lpaClose = NULL; + AREAP lpaClose = NULL; + PHB_ITEM pStruct = NULL; DBTRANSINFO dbTransInfo; - USHORT uiPrevArea; + USHORT uiPrevArea, uiCount, uiSwap; ERRCODE errCode; memset( &dbTransInfo, 0, sizeof( DBTRANSINFO ) ); @@ -4294,10 +4310,7 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, if( fExport ) { - PHB_ITEM pStruct = NULL; - - lpaSource = pArea; - errCode = hb_dbTransStruct( lpaSource, NULL, &dbTransInfo, + errCode = hb_dbTransStruct( pArea, NULL, &dbTransInfo, &pStruct, pFields ); if( errCode == SUCCESS ) { @@ -4305,26 +4318,71 @@ static ERRCODE hb_rddTransRecords( AREAP pArea, TRUE, 0, "", szCpId, ulConnection ); if( errCode == SUCCESS ) { - dbTransInfo.lpaDest = lpaClose = lpaDest = + dbTransInfo.lpaDest = lpaClose = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + if( pDelim ) + { + SELF_INFO( dbTransInfo.lpaDest, DBI_SETDELIMITER, pDelim ); + } } } - if( pStruct ) - hb_itemRelease( pStruct ); } else { - lpaDest = pArea; - errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, - szCpId, ulConnection ); - if( errCode == SUCCESS ) + LPRDDNODE pRddNode = hb_rddFindNode( szDriver, NULL ); + + if( !pRddNode ) { - lpaClose = lpaSource = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); - errCode = hb_dbTransStruct( lpaSource, lpaDest, &dbTransInfo, - NULL, pFields ); + hb_errRT_DBCMD( EG_ARG, EDBCMD_USE_BADPARAMETER, NULL, "DBUSEAREA" ); + return FAILURE; + } + + if( pRddNode->uiType == RDT_TRANSFER ) + { + errCode = hb_dbTransStruct( pArea, NULL, &dbTransInfo, + &pStruct, pFields ); + + /* revert area and items */ + dbTransInfo.lpaDest = dbTransInfo.lpaSource; + for( uiCount = 0; uiCount < dbTransInfo.uiItemCount; ++uiCount ) + { + uiSwap = dbTransInfo.lpTransItems[uiCount].uiSource; + dbTransInfo.lpTransItems[uiCount].uiSource = + dbTransInfo.lpTransItems[uiCount].uiDest; + dbTransInfo.lpTransItems[uiCount].uiDest = uiSwap; + } + + if( errCode == SUCCESS ) + { + errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, + szCpId, ulConnection, pStruct ); + if( errCode == SUCCESS ) + { + lpaClose = dbTransInfo.lpaSource = + ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + if( pDelim ) + { + SELF_INFO( dbTransInfo.lpaSource, DBI_SETDELIMITER, pDelim ); + } + } + } + } + else + { + errCode = hb_rddOpenTable( szFileName, szDriver, 0, "", TRUE, TRUE, + szCpId, ulConnection, NULL ); + if( errCode == SUCCESS ) + { + lpaClose = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); + errCode = hb_dbTransStruct( lpaClose, pArea, &dbTransInfo, + NULL, pFields ); + } } } + if( pStruct ) + hb_itemRelease( pStruct ); + if( errCode == SUCCESS ) { hb_rddSelectWorkAreaNumber( dbTransInfo.lpaSource->uiArea ); @@ -4378,7 +4436,8 @@ HB_FUNC( __DBAPP ) hb_param( 5, HB_IT_NUMERIC ), /* Next */ ISNIL( 6 ) ? NULL : hb_param( 6, HB_IT_ANY ), /* RecID */ hb_param( 7, HB_IT_LOGICAL ), /* Rest */ - hb_parc( 10 ) ); /* Codepage */ + hb_parc( 10 ), /* Codepage */ + hb_param( 11, HB_IT_STRING ) );/* Delimiter */ } else { @@ -4407,7 +4466,8 @@ HB_FUNC( __DBCOPY ) hb_param( 5, HB_IT_NUMERIC ), /* Next */ ISNIL( 6 ) ? NULL : hb_param( 6, HB_IT_ANY ), /* RecID */ hb_param( 7, HB_IT_LOGICAL ), /* Rest */ - hb_parc( 10 ) ); /* Codepage */ + hb_parc( 10 ), /* Codepage */ + hb_param( 11, HB_IT_STRING ) );/* Delimiter */ } else { diff --git a/harbour/source/rdd/dbf1.c b/harbour/source/rdd/dbf1.c index 330f1f96e4..f2c423fa90 100644 --- a/harbour/source/rdd/dbf1.c +++ b/harbour/source/rdd/dbf1.c @@ -1098,6 +1098,11 @@ static ERRCODE hb_dbfAddField( DBFAREAP pArea, LPDBFIELDINFO pFieldInfo ) { HB_TRACE(HB_TR_DEBUG, ("hb_dbfAddField(%p, %p)", pArea, pFieldInfo)); + if( pFieldInfo->uiType == HB_IT_MEMO && pArea->bMemoType == DB_MEMO_SMT ) + { + pFieldInfo->uiLen = 10; + } + /* Update field offset */ pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; pArea->uiRecordLen += pFieldInfo->uiLen; @@ -1265,7 +1270,7 @@ static ERRCODE hb_dbfFlush( DBFAREAP pArea ) } /* - * Replace the current record. + * Retrieve current record buffer */ static ERRCODE hb_dbfGetRec( DBFAREAP pArea, BYTE ** pBuffer ) { @@ -1420,18 +1425,16 @@ static ERRCODE hb_dbfGetValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) if( pField->uiDec ) { hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, - ( int ) pField->uiLen - ( ( int ) pField->uiDec + 1 ), + ( int ) ( pField->uiLen - pField->uiDec - 1 ), ( int ) pField->uiDec ); } - else if( pField->uiLen > 9 ) + else if( fDbl ) { - hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, - ( int ) pField->uiLen, 0 ); + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); } else { - hb_itemPutNLLen( pItem, ( LONG ) ( fDbl ? dVal : lVal ), - ( int ) pField->uiLen ); + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); } } break; @@ -1669,8 +1672,7 @@ static ERRCODE hb_dbfPutValue( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_itemGetCPtr( pItem ), uiSize ); #ifndef HB_CDP_SUPPORT_OFF - if( HB_IS_STRING( pItem ) ) - hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); #endif memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, ' ', pField->uiLen - uiSize ); @@ -1933,8 +1935,8 @@ static ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent ) /* Alloc field offsets array */ if( uiFieldExtent ) { - pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT * ) ); - memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT * ) ); + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); } return SUCCESS; @@ -2096,9 +2098,6 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->szDataFileName = hb_strdup( ( char * ) szFileName ); - /* Size for deleted flag */ - pArea->uiRecordLen = 1; - if( pArea->bTableType == 0 ) { pItem = hb_itemPutNI( pItem, 0 ); @@ -2162,6 +2161,9 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->fHasMemo = fError = FALSE; + /* Size for deleted flag */ + pArea->uiRecordLen = 1; + for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ ) { LPFIELD pField = pArea->lpFields + uiCount; @@ -2196,7 +2198,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; pArea->fHasMemo = TRUE; break; @@ -2228,14 +2230,14 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_LONG: pThisField->bType = 'N'; pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = ( BYTE ) pField->uiDec; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_DOUBLE: @@ -2243,7 +2245,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) pField->uiLen = 8; pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = ( BYTE ) pField->uiDec; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; case HB_IT_INTEGER: @@ -2255,7 +2257,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo ) } pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bDec = 0; - pArea->uiRecordLen += pThisField->bLen; + pArea->uiRecordLen += pField->uiLen; break; default: diff --git a/harbour/source/rdd/delim1.c b/harbour/source/rdd/delim1.c index b27f296b0f..349ac6f1f4 100644 --- a/harbour/source/rdd/delim1.c +++ b/harbour/source/rdd/delim1.c @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * DELIMITED RDD module + * DELIM RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -53,112 +53,1404 @@ #include "hbapi.h" #include "hbinit.h" #include "hbvm.h" +#include "hbset.h" +#include "hbdate.h" #include "hbapirdd.h" #include "hbapiitm.h" +#include "hbapilng.h" #include "hbapierr.h" +#include "hbdbferr.h" #include "hbrdddel.h" #include "rddsys.ch" +#define SUPERTABLE (&delimSuper) + static RDDFUNCS delimSuper; -static RDDFUNCS delimTable = { hb_delimBof, - hb_delimEof, - hb_delimFound, - hb_delimGoBottom, - hb_delimGoTo, - hb_delimGoToId, - hb_delimGoTop, - hb_delimSeek, - hb_delimSkip, - hb_delimSkipFilter, - hb_delimSkipRaw, - hb_delimAddField, - hb_delimAppend, - hb_delimCreateFields, - hb_delimDeleteRec, - hb_delimDeleted, - hb_delimFieldCount, - hb_delimFieldDisplay, - hb_delimFieldInfo, - hb_delimFieldName, - hb_delimFlush, - hb_delimGetRec, - hb_delimGetValue, - hb_delimGetVarLen, - hb_delimGoCold, - hb_delimGoHot, - hb_delimPutRec, - hb_delimPutValue, - hb_delimRecall, - hb_delimRecCount, - hb_delimRecInfo, - hb_delimRecNo, - hb_delimRecId, - hb_delimSetFieldExtent, - hb_delimAlias, - hb_delimClose, - hb_delimCreate, - hb_delimInfo, - hb_delimNewArea, - hb_delimOpen, - hb_delimRelease, - hb_delimStructSize, - hb_delimSysName, - hb_delimEval, - hb_delimPack, - hb_delimPackRec, - hb_delimSort, - hb_delimTrans, - hb_delimTransRec, - hb_delimZap, - hb_delimChildEnd, - hb_delimChildStart, - hb_delimChildSync, - hb_delimSyncChildren, - hb_delimClearRel, - hb_delimForceRel, - hb_delimRelArea, - hb_delimRelEval, - hb_delimRelText, - hb_delimSetRel, - hb_delimOrderListAdd, - hb_delimOrderListClear, - hb_delimOrderListDelete, - hb_delimOrderListFocus, - hb_delimOrderListRebuild, - hb_delimOrderCondition, - hb_delimOrderCreate, - hb_delimOrderDestroy, - hb_delimOrderInfo, - hb_delimClearFilter, - hb_delimClearLocate, - hb_delimClearScope, - hb_delimCountScope, - hb_delimFilterText, - hb_delimScopeInfo, - hb_delimSetFilter, - hb_delimSetLocate, - hb_delimSetScope, - hb_delimSkipScope, - hb_delimLocate, - hb_delimCompile, - hb_delimError, - hb_delimEvalBlock, - hb_delimRawLock, - hb_delimLock, - hb_delimUnLock, - hb_delimCloseMemFile, - hb_delimCreateMemFile, - hb_delimGetValueFile, - hb_delimOpenMemFile, - hb_delimPutValueFile, - hb_delimReadDBHeader, - hb_delimWriteDBHeader, - hb_delimInit, - hb_delimExit, - hb_delimDrop, - hb_delimExists, - hb_delimRddInfo, - hb_delimWhoCares +static USHORT s_uiNumLength[ 9 ] = { 0, 4, 6, 8, 11, 13, 16, 18, 20 }; + +static void hb_delimInitArea( DELIMAREAP pArea, char * szFileName ) +{ + /* Allocate only after succesfully open file */ + pArea->szFileName = hb_strdup( szFileName ); + + /* set line separator: EOL */ +#ifdef __XHARBOUR__ + if( hb_itemGetCLen( hb_set.HB_SET_EOL ) == 0 ) + pArea->szEol = hb_strdup( hb_conNewLine() ); + else + pArea->szEol = hb_strdup( hb_itemGetCPtr( hb_set.HB_SET_EOL ) ); +#else + pArea->szEol = hb_strdup( hb_conNewLine() ); +#endif + pArea->uiEolLen = strlen( pArea->szEol ); + + /* allocate record buffer, one additional byte is for deleted flag */ + pArea->pRecord = ( BYTE * ) hb_xgrab( pArea->uiRecordLen + 1 ); + /* pseudo deleted flag */ + *pArea->pRecord++ = ' '; + + /* Allocate IO buffer */ + pArea->ulBufferSize += pArea->uiEolLen; + pArea->pBuffer = ( BYTE * ) hb_xgrab( pArea->ulBufferSize ); + + pArea->ulRecCount = 0; + pArea->ulFileSize = 0; + pArea->ulBufferRead = pArea->ulBufferIndex = 0; +} + +static void hb_delimClearRecordBuffer( DELIMAREAP pArea ) +{ + memset( pArea->pRecord, ' ', pArea->uiRecordLen ); +} + +static ULONG hb_delimEncodeBuffer( DELIMAREAP pArea ) +{ + ULONG ulSize; + USHORT uiField, uiLen; + LPFIELD pField; + BYTE * pBuffer, * pFieldBuf; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimEncodeBuffer(%p)", pArea)); + + /* mark the read buffer as empty */ + pArea->ulBufferRead = pArea->ulBufferIndex = 0; + + pBuffer = pArea->pBuffer; + ulSize = 0; + for( uiField = 0; uiField < pArea->uiFieldCount; ++uiField ) + { + pField = pArea->lpFields + uiField; + pFieldBuf = pArea->pRecord + pArea->pFieldOffset[ uiField ]; + if( ulSize ) + pBuffer[ ulSize++ ] = pArea->cSeparator; + + switch( pField->uiType ) + { + case HB_IT_STRING: + uiLen = pField->uiLen; + while( uiLen && pFieldBuf[ uiLen - 1 ] == ' ' ) + --uiLen; + if( pArea->fDelim ) + { + pBuffer[ ulSize++ ] = pArea->cDelim; + memcpy( pBuffer + ulSize, pFieldBuf, uiLen ); + ulSize += uiLen; + pBuffer[ ulSize++ ] = pArea->cDelim; + } + else + { + memcpy( pBuffer + ulSize, pFieldBuf, uiLen ); + ulSize += uiLen; + } + break; + + case HB_IT_LOGICAL: + pBuffer[ ulSize++ ] = ( *pFieldBuf == 'T' || *pFieldBuf == 't' || + *pFieldBuf == 'Y' || *pFieldBuf == 'y' ) ? + 'T' : 'F'; + break; + + case HB_IT_DATE: + uiLen = 0; + while( uiLen < 8 && pFieldBuf[ uiLen ] == ' ' ) + ++uiLen; + if( uiLen < 8 ) + { + memcpy( pBuffer + ulSize, pFieldBuf, 8 ); + ulSize += 8; + } + break; + + case HB_IT_LONG: + uiLen = 0; + while( uiLen < pField->uiLen && pFieldBuf[ uiLen ] == ' ' ) + ++uiLen; + if( uiLen < pField->uiLen ) + { + memcpy( pBuffer + ulSize, pFieldBuf + uiLen, pField->uiLen - uiLen ); + ulSize += pField->uiLen - uiLen; + } + else + { + pBuffer[ ulSize++ ] = '0'; + if( pField->uiDec ) + { + pBuffer[ ulSize++ ] = '.'; + memset( pBuffer + ulSize, '0', pField->uiDec ); + ulSize += pField->uiDec; + } + } + break; + + case HB_IT_MEMO: + default: + if( ulSize ) + --ulSize; + break; + } + } + memcpy( pBuffer + ulSize, pArea->szEol, pArea->uiEolLen ); + ulSize += pArea->uiEolLen; + + return ulSize; +} + +static int hb_delimNextChar( DELIMAREAP pArea ) +{ + if( pArea->ulBufferIndex + pArea->uiEolLen >= pArea->ulBufferRead && + ( pArea->ulBufferRead == 0 || + pArea->ulBufferRead >= pArea->ulBufferSize - 1 ) ) + { + USHORT uiLeft = ( USHORT ) pArea->ulBufferRead - pArea->ulBufferIndex; + + if( uiLeft ) + memcpy( pArea->pBuffer, + pArea->pBuffer + pArea->ulBufferIndex, uiLeft ); + pArea->ulBufferStart += pArea->ulBufferIndex; + pArea->ulBufferIndex = 0; + hb_fsSeekLarge( pArea->hFile, pArea->ulBufferStart + uiLeft, FS_SET ); + pArea->ulBufferRead = hb_fsReadLarge( pArea->hFile, + pArea->pBuffer + uiLeft, + pArea->ulBufferSize - uiLeft ); + if( pArea->ulBufferRead > 0 && + pArea->pBuffer[ pArea->ulBufferRead + uiLeft - 1 ] == '\032' ) + pArea->ulBufferRead--; + pArea->ulBufferRead += uiLeft; + } + + if( pArea->ulBufferIndex + pArea->uiEolLen <= pArea->ulBufferRead && + memcmp( pArea->pBuffer + pArea->ulBufferIndex, + pArea->szEol, pArea->uiEolLen ) == 0 ) + { + pArea->ulBufferIndex += pArea->uiEolLen; + pArea->ulNextOffset = pArea->ulBufferStart + pArea->ulBufferIndex; + return -1; + } + else if( pArea->ulBufferIndex < pArea->ulBufferRead ) + { + return pArea->pBuffer[ pArea->ulBufferIndex++ ]; + } + + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + return -2; +} + +/* + * Read record, decode it to buffer and set next record offset + */ +static ERRCODE hb_delimReadRecord( DELIMAREAP pArea ) +{ + USHORT uiField, uiLen, uiSize; + HB_TYPE uiType; + LPFIELD pField; + BYTE * pFieldBuf, buffer[ 256 ]; + char cStop; + int ch = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimReadRecord(%p)", pArea)); + + if( pArea->ulBufferStart <= pArea->ulRecordOffset && + pArea->ulBufferStart + pArea->ulBufferRead > pArea->ulRecordOffset ) + { + pArea->ulBufferIndex = pArea->ulRecordOffset - pArea->ulBufferStart; + } + else + { + pArea->ulBufferStart = pArea->ulRecordOffset; + pArea->ulBufferRead = pArea->ulBufferIndex = 0; + } + + /* clear the record buffer */ + hb_delimClearRecordBuffer( pArea ); + + for( uiField = 0; uiField < pArea->uiFieldCount; ++uiField ) + { + pField = pArea->lpFields + uiField; + uiType = pField->uiType; + if( uiType == HB_IT_STRING || uiType == HB_IT_LOGICAL || + uiType == HB_IT_DATE || uiType == HB_IT_LONG ) + { + uiSize = 0; + uiLen = pField->uiLen; + pFieldBuf = pArea->pRecord + pArea->pFieldOffset[ uiField ]; + + /* ignore leading spaces */ + do + ch = hb_delimNextChar( pArea ); + while( ch == ' ' ); + + /* set the stop character */ + if( pArea->fDelim && ch == pArea->cDelim ) + { + cStop = pArea->cDelim; + ch = hb_delimNextChar( pArea ); + } + else + cStop = pArea->cSeparator; + + /* + * Clipper uses differ rules for character fields, they + * can be terminated only with valid stop character, when + * other fields also by length + */ + if( pField->uiType == HB_IT_STRING ) + { + while( ch >= 0 && ch != cStop ) + { + if( uiSize < uiLen ) + pFieldBuf[ uiSize++ ] = ( BYTE ) ch; + ch = hb_delimNextChar( pArea ); + } + } + else + { + while( ch >= 0 && ch != cStop && uiSize < uiLen ) + { + buffer[ uiSize++ ] = ( BYTE ) ch; + ch = hb_delimNextChar( pArea ); + } + buffer[ uiSize ] = '\0'; + + if( pField->uiType == HB_IT_LOGICAL ) + { + *pFieldBuf = ( *buffer == 'T' || *buffer == 't' || + *buffer == 'Y' || *buffer == 'y' ) ? 'T' : 'F'; + } + else if( pField->uiType == HB_IT_DATE ) + { + if( uiSize == 8 && hb_dateEncStr( ( char * ) buffer ) != 0 ) + memcpy( pFieldBuf, buffer, 8 ); + } + else + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) buffer, uiSize, &lVal, &dVal ); + if( fDbl ) + pArea->valResult = hb_itemPutNDLen( pArea->valResult, dVal, + uiLen - pField->uiDec - 1, pField->uiDec ); + else + pArea->valResult = hb_itemPutNIntLen( pArea->valResult, + lVal, uiLen ); + hb_itemStrBuf( ( char * ) buffer, pArea->valResult, uiLen, pField->uiDec ); + /* TODO: RT error on width range */ + memcpy( pFieldBuf, buffer, uiLen ); + } + } + + /* ignore all character to the next field separator */ + while( ch >= 0 && ch != pArea->cSeparator ) + ch = hb_delimNextChar( pArea ); + + /* stop reading on EOL */ + if( ch < 0 ) + break; + } + + } + /* ignore all character to the end of line */ + while( ch >= 0 ) + ch = hb_delimNextChar( pArea ); + + if( ch == -2 && + pArea->ulRecordOffset == pArea->ulBufferStart + pArea->ulBufferIndex ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + } + else + { + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + } + + return SUCCESS; +} + +static ERRCODE hb_delimNextRecord( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimNextRecord(%p)", pArea)); + + if( pArea->fPositioned ) + { + if( pArea->ulNextOffset == ( HB_FOFFSET ) -1 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_delimClearRecordBuffer( pArea ); + } + else + { + pArea->ulRecNo++; + pArea->ulRecordOffset = pArea->ulNextOffset; + return hb_delimReadRecord( pArea ); + } + } + return SUCCESS; +} + +/* + * -- DELIM METHODS -- + */ + +/* + * Position cursor at the first record. + */ +static ERRCODE hb_delimGoTop( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoTop(%p)", pArea)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fTop = TRUE; + pArea->fBottom = FALSE; + + pArea->ulRecordOffset = 0; + pArea->ulRecNo = 1; + if( hb_delimReadRecord( pArea ) != SUCCESS ) + return FAILURE; + + return SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); +} + +/* + * Reposition cursor, regardless of filter. + */ +static ERRCODE hb_delimSkipRaw( DELIMAREAP pArea, LONG lToSkip ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimSkipRaw(%p,%ld)", pArea, lToSkip)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( lToSkip != 1 ) + return FAILURE; + else + return hb_delimNextRecord( pArea ); +} + +/* + * Determine deleted status for a record. + */ +static ERRCODE hb_delimDeleted( DELIMAREAP pArea, BOOL * pDeleted ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimDeleted(%p,%p)", pArea, pDeleted)); + + HB_SYMBOL_UNUSED( pArea ); + + * pDeleted = FALSE; + + return SUCCESS; +} + +/* + * Obtain number of records in WorkArea. + */ +static ERRCODE hb_delimRecCount( DELIMAREAP pArea, ULONG * pRecCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecCount(%p,%p)", pArea, pRecCount)); + + * pRecCount = pArea->ulRecCount; + + return SUCCESS; +} + +/* + * Obtain physical row number at current WorkArea cursor position. + */ +static ERRCODE hb_delimRecNo( DELIMAREAP pArea, ULONG * pulRecNo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecNo(%p,%p)", pArea, pulRecNo)); + + *pulRecNo = pArea->ulRecNo; + + return SUCCESS; +} + +/* + * Obtain physical row ID at current WorkArea cursor position. + */ +static ERRCODE hb_delimRecId( DELIMAREAP pArea, PHB_ITEM pRecNo ) +{ + ERRCODE errCode; + ULONG ulRecNo; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimRecId(%p,%p)", pArea, pRecNo)); + + errCode = SELF_RECNO( ( AREAP ) pArea, &ulRecNo ); + +#ifdef HB_C52_STRICT + /* this is for strict Clipper compatibility but IMHO Clipper should not + do that and always set fixed size independent to the record number */ + if( ulRecNo < 10000000 ) + { + hb_itemPutNLLen( pRecNo, ulRecNo, 7 ); + } + else + { + hb_itemPutNLLen( pRecNo, ulRecNo, 10 ); + } +#else + hb_itemPutNInt( pRecNo, ulRecNo ); +#endif + return errCode; +} + +/* + * Append a record to the WorkArea. + */ +static ERRCODE hb_delimAppend( DELIMAREAP pArea, BOOL fUnLockAll ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimAppend(%p,%d)", pArea, (int) fUnLockAll)); + + HB_SYMBOL_UNUSED( fUnLockAll ); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->ulRecordOffset = pArea->ulFileSize; + pArea->ulRecNo = ++pArea->ulRecCount; + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + hb_delimClearRecordBuffer( pArea ); + + return SUCCESS; +} + +/* + * Delete a record. + */ +static ERRCODE hb_delimDeleteRec( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimDeleteRec(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + pArea->ulRecCount--; + pArea->fEof = TRUE; + pArea->fPositioned = pArea->fRecordChanged = FALSE; + hb_delimClearRecordBuffer( pArea ); + } + + return SUCCESS; +} + +/* + * Obtain the current value of a field. + */ +static ERRCODE hb_delimGetValue( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + LPFIELD pField; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + --uiIndex; + pField = pArea->lpFields + uiIndex; + switch( pField->uiType ) + { + case HB_IT_STRING: +#ifndef HB_CDP_SUPPORT_OFF + if( pArea->cdPage != hb_cdp_page ) + { + char * pVal = ( char * ) hb_xgrab( pField->uiLen + 1 ); + memcpy( pVal, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], pField->uiLen ); + pVal[ pField->uiLen ] = '\0'; + hb_cdpnTranslate( pVal, pArea->cdPage, hb_cdp_page, pField->uiLen ); + hb_itemPutCPtr( pItem, pVal, pField->uiLen ); + } + else +#endif + { + hb_itemPutCL( pItem, ( char * ) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen ); + } + break; + + case HB_IT_LOGICAL: + switch( pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] ) + { + case 'T': + case 't': + case 'Y': + case 'y': + hb_itemPutL( pItem, TRUE ); + break; + default: + hb_itemPutL( pItem, FALSE ); + break; + } + break; + + case HB_IT_DATE: + { + char szBuffer[ 9 ]; + memcpy( szBuffer, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], 8 ); + szBuffer[ 8 ] = 0; + hb_itemPutDS( pItem, szBuffer ); + } + break; + + case HB_IT_LONG: + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen, &lVal, &dVal ); + + + if( pField->uiDec ) + { + hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, + ( int ) ( pField->uiLen - pField->uiDec - 1 ), + ( int ) pField->uiDec ); + } + else if( fDbl ) + { + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); + } + else + { + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); + } + } + break; + + case HB_IT_MEMO: + hb_itemPutC( pItem, "" ); + break; + + default: + { + PHB_ITEM pError; + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_DATATYPE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, EDBF_DATATYPE ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + } + + return SUCCESS; +} + +/* + * Assign a value to a field. + */ +static ERRCODE hb_delimPutValue( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + char szBuffer[ 256 ]; + ERRCODE uiError; + LPFIELD pField; + USHORT uiSize; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimPutValue(%p,%hu,%p)", pArea, uiIndex, pItem)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + uiError = SUCCESS; + --uiIndex; + pField = pArea->lpFields + uiIndex; + if( pField->uiType != HB_IT_MEMO ) + { + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + if( pField->uiType == HB_IT_STRING ) + { + uiSize = ( USHORT ) hb_itemGetCLen( pItem ); + if( uiSize > pField->uiLen ) + uiSize = pField->uiLen; + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + hb_itemGetCPtr( pItem ), uiSize ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); +#endif + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, + ' ', pField->uiLen - uiSize ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_DATE( pItem ) ) + { + if( pField->uiType == HB_IT_DATE ) + { + hb_itemGetDS( pItem, szBuffer ); + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], szBuffer, 8 ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_NUMBER( pItem ) ) + { + if( pField->uiType == HB_IT_LONG ) + { + if( hb_itemStrBuf( szBuffer, pItem, pField->uiLen, pField->uiDec ) ) + { + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + szBuffer, pField->uiLen ); + } + else + { + uiError = EDBF_DATAWIDTH; + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + '*', pField->uiLen ); + } + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_LOGICAL( pItem ) ) + { + if( pField->uiType == HB_IT_LOGICAL ) + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] = hb_itemGetL( pItem ) ? 'T' : 'F'; + else + uiError = EDBF_DATATYPE; + } + else + uiError = EDBF_DATATYPE; + } + + if( uiError != SUCCESS ) + { + PHB_ITEM pError= hb_errNew(); + USHORT uiGenCode = uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : EDBF_DATATYPE; + + hb_errPutGenCode( pError, uiGenCode ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return SUCCESS; + /* return FAILURE; */ + } + + return SUCCESS; +} + +/* + * Replace the current record. + */ +static ERRCODE hb_delimPutRec( DELIMAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimPutRec(%p,%p)", pArea, pBuffer)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + /* Copy data to buffer */ + memcpy( pArea->pRecord, pBuffer + 1, pArea->uiRecordLen ); + + return SUCCESS; +} + +/* + * Retrieve current record buffer + */ +static ERRCODE hb_delimGetRec( DELIMAREAP pArea, BYTE ** pBufferPtr ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGetRec(%p,%p)", pArea, pBufferPtr)); + + *pBufferPtr = pArea->pRecord - 1; + + return SUCCESS; +} + +/* + * Copy one or more records from one WorkArea to another. + */ +static ERRCODE hb_delimTrans( DELIMAREAP pArea, LPDBTRANSINFO pTransInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimTrans(%p, %p)", pArea, pTransInfo)); + + if( pTransInfo->uiFlags & DBTF_MATCH ) + { + if( !pArea->fTransRec || pArea->cdPage != pTransInfo->lpaDest->cdPage ) + pTransInfo->uiFlags &= ~DBTF_PUTREC; + else if( pArea->rddID == pTransInfo->lpaDest->rddID ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + { + PHB_ITEM pPutRec = hb_itemPutL( NULL, FALSE ); + SELF_INFO( ( AREAP ) pTransInfo->lpaDest, DBI_CANPUTREC, pPutRec ); + if( hb_itemGetL( pPutRec ) ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + pTransInfo->uiFlags &= ~DBTF_PUTREC; + hb_itemRelease( pPutRec ); + } + } + return SUPER_TRANS( ( AREAP ) pArea, pTransInfo ); +} + +/* + * Perform a write of WorkArea memory to the data store. + */ +static ERRCODE hb_delimGoCold( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoCold(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + ULONG ulSize = hb_delimEncodeBuffer( pArea ); + + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + if( hb_fsWriteLarge( pArea->hFile, pArea->pBuffer, ulSize ) != ulSize ) + { + PHB_ITEM pError = hb_errNew(); + + hb_errPutGenCode( pError, EG_WRITE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_WRITE ) ); + hb_errPutSubCode( pError, EDBF_WRITE ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutFileName( pError, pArea->szFileName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->ulFileSize += ulSize; + pArea->ulNextOffset = pArea->ulFileSize; + pArea->fRecordChanged = FALSE; + pArea->fFlush = TRUE; + } + return SUCCESS; +} + +/* + * Mark the WorkArea data buffer as hot. + */ +static ERRCODE hb_delimGoHot( DELIMAREAP pArea ) +{ + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimGoHot(%p)", pArea)); + + if( pArea->fReadonly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, EDBF_READONLY ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->fRecordChanged = TRUE; + return SUCCESS; +} + +/* + * Write data buffer to the data store. + */ +static ERRCODE hb_delimFlush( DELIMAREAP pArea ) +{ + ERRCODE uiError; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimFlush(%p)", pArea)); + + uiError = SELF_GOCOLD( ( AREAP ) pArea ); + + if( pArea->fFlush ) + { + hb_fsSeekLarge( pArea->hFile, pArea->ulFileSize, FS_SET ); + hb_fsWrite( pArea->hFile, ( BYTE * ) "\032", 1 ); + if( hb_set.HB_SET_HARDCOMMIT ) + { + hb_fsCommit( pArea->hFile ); + pArea->fFlush = FALSE; + } + } + + return uiError; +} + +/* + * Retrieve information about the current table/driver. + */ +static ERRCODE hb_delimInfo( DELIMAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimInfo(%p,%hu,%p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_CANPUTREC: + hb_itemPutL( pItem, pArea->fTransRec ); + break; + + case DBI_GETRECSIZE: + hb_itemPutNL( pItem, pArea->uiRecordLen ); + break; + + case DBI_GETDELIMITER: + { + char szDelim[ 2 ] = { pArea->cDelim, '\0' }; + hb_itemPutC( pItem, szDelim ); + break; + } + case DBI_SETDELIMITER: + if( hb_itemType( pItem ) & HB_IT_STRING ) + { + char * szDelim = hb_itemGetCPtr( pItem ); + if( hb_stricmp( szDelim, "BLANK" ) == 0 ) + { + pArea->fDelim = FALSE; + pArea->cDelim = '\0'; + pArea->cSeparator = ' '; + } + else if( *szDelim ) + pArea->cDelim = *szDelim; + } + break; + + case DBI_SEPARATOR: + { + char szSeparator[ 2 ] = { pArea->cSeparator, '\0' }; + char * szNew = hb_itemGetCPtr( pItem ); + if( *szNew ) + pArea->cSeparator = *szNew; + hb_itemPutC( pItem, szSeparator ); + break; + } + case DBI_FULLPATH: + hb_itemPutC( pItem, pArea->szFileName); + break; + + case DBI_FILEHANDLE: + hb_itemPutNInt( pItem, ( HB_LONG ) pArea->hFile ); + break; + + case DBI_SHARED: + hb_itemPutL( pItem, pArea->fShared ); + break; + + case DBI_ISREADONLY: + hb_itemPutL( pItem, pArea->fReadonly ); + break; + + case DBI_DB_VERSION: + case DBI_RDD_VERSION: + { + char szBuf[ 64 ]; + int iSub = hb_itemGetNI( pItem ); + + if( iSub == 1 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s)", 0, 1, "DELIM" ); + else if( iSub == 2 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s:%d)", 0, 1, "DELIM", pArea->rddID ); + else + snprintf( szBuf, sizeof( szBuf ), "%d.%d", 0, 1 ); + hb_itemPutC( pItem, szBuf ); + break; + } + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Add a field to the WorkArea. + */ +static ERRCODE hb_delimAddField( DELIMAREAP pArea, LPDBFIELDINFO pFieldInfo ) +{ + USHORT uiDelim = 0; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimAddField(%p, %p)", pArea, pFieldInfo)); + + switch( pFieldInfo->uiType ) + { + case HB_IT_STRING: + uiDelim = 2; + break; + + case HB_IT_MEMO: + pFieldInfo->uiLen = 0; + pArea->fTransRec = FALSE; + break; + + case HB_IT_ANY: + if( pFieldInfo->uiLen == 3 ) + { + pFieldInfo->uiType = HB_IT_DATE; + pFieldInfo->uiLen = 8; + } + else if( pFieldInfo->uiLen < 6 ) + { + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + } + else + { + pFieldInfo->uiType = HB_IT_MEMO; + pFieldInfo->uiLen = 0; + } + pArea->fTransRec = FALSE; + break; + + case HB_IT_DATE: + if( pFieldInfo->uiLen != 8 ) + { + pFieldInfo->uiLen = 8; + pArea->fTransRec = FALSE; + } + break; + + case HB_IT_INTEGER: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + pArea->fTransRec = FALSE; + break; + + case HB_IT_DOUBLE: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = 20; + pArea->fTransRec = FALSE; + break; + } + + /* Update field offset */ + pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; + pArea->uiRecordLen += pFieldInfo->uiLen; + pArea->ulBufferSize += pFieldInfo->uiLen + uiDelim + 1; + + return SUPER_ADDFIELD( ( AREAP ) pArea, pFieldInfo ); +} + +/* + * Establish the extent of the array of fields for a WorkArea. + */ +static ERRCODE hb_delimSetFieldExtent( DELIMAREAP pArea, USHORT uiFieldExtent ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimSetFieldExtent(%p,%hu)", pArea, uiFieldExtent)); + + if( SUPER_SETFIELDEXTENT( ( AREAP ) pArea, uiFieldExtent ) == FAILURE ) + return FAILURE; + + /* Alloc field offsets array */ + if( uiFieldExtent ) + { + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); + } + + return SUCCESS; +} + +/* + * Clear the WorkArea for use. + */ +static ERRCODE hb_delimNewArea( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimNewArea(%p)", pArea)); + + if( SUPER_NEW( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->hFile = FS_ERROR; + pArea->fTransRec = TRUE; + pArea->uiRecordLen = 0; + pArea->ulBufferSize = 0; + + /* set character field delimiter */ + pArea->fDelim = TRUE; + pArea->cDelim = '"'; + + /* set field delimiter */ + pArea->cSeparator = ','; + + return SUCCESS; +} + +/* + * Retrieve the size of the WorkArea structure. + */ +static ERRCODE hb_delimStructSize( DELIMAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimStrucSize(%p,%p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( DELIMAREA ); + return SUCCESS; +} + +/* + * Close the table in the WorkArea. + */ +static ERRCODE hb_delimClose( DELIMAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimClose(%p)", pArea)); + + SUPER_CLOSE( ( AREAP ) pArea ); + + /* Update record and unlock records */ + if( pArea->hFile != FS_ERROR ) + { + SELF_FLUSH( ( AREAP ) pArea ); + hb_fsClose( pArea->hFile ); + pArea->hFile = FS_ERROR; + } + + if( pArea->pFieldOffset ) + { + hb_xfree( pArea->pFieldOffset ); + pArea->pFieldOffset = NULL; + } + if( pArea->pRecord ) + { + hb_xfree( pArea->pRecord - 1 ); + pArea->pRecord = NULL; + } + if( pArea->pBuffer ) + { + hb_xfree( pArea->pBuffer ); + pArea->pBuffer = NULL; + } + if( pArea->szEol ) + { + hb_xfree( pArea->szEol ); + pArea->szEol = NULL; + } + if( pArea->szFileName ) + { + hb_xfree( pArea->szFileName ); + pArea->szFileName = NULL; + } + + return SUCCESS; +} + +/* + * Create a data store in the specified WorkArea. + */ +static ERRCODE hb_delimCreate( DELIMAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + ERRCODE errCode = SUCCESS; + PHB_FNAME pFileName; + PHB_ITEM pError = NULL; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimCreate(%p,%p)", pArea, pCreateInfo)); + + pArea->fShared = FALSE; /* pCreateInfo->fShared; */ + pArea->fReadonly = FALSE; /* pCreateInfo->fReadonly */ +#ifndef HB_CDP_SUPPORT_OFF + if( pCreateInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pCreateInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + pFileName = hb_fsFNameSplit( ( char * ) pCreateInfo->abName ); + if( ! pFileName->szExtension ) + { + PHB_ITEM pItem = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pItem ); + pFileName->szExtension = hb_itemGetCPtr( pItem ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pItem ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pCreateInfo->abName, _POSIX_PATH_MAX ); + } + hb_xfree( pFileName ); + + /* Try create */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, + FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_CREATE( ( AREAP ) pArea, pCreateInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return errCode; + } + + hb_delimInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Open a data store in the WorkArea. + */ +static ERRCODE hb_delimOpen( DELIMAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + PHB_ITEM pError = NULL; + PHB_FNAME pFileName; + ERRCODE errCode; + USHORT uiFlags; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + char szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_delimOpen(%p,%p)", pArea, pOpenInfo)); + + pArea->fShared = TRUE; /* pOpenInfo->fShared; */ + pArea->fReadonly = TRUE; /* pOpenInfo->fReadonly; */ +#ifndef HB_CDP_SUPPORT_OFF + if( pOpenInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pOpenInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + uiFlags = ( pArea->fReadonly ? FO_READ : FO_READWRITE ) | + ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); + + pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); + /* Add default file name extension if necessary */ + if( ! pFileName->szExtension ) + { + PHB_ITEM pFileExt = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pFileExt ); + pFileName->szExtension = hb_itemGetCPtr( pFileExt ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pFileExt ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pOpenInfo->abName, _POSIX_PATH_MAX ); + } + + /* Create default alias if necessary */ + if( !pOpenInfo->atomAlias && pFileName->szName ) + { + hb_strncpyUpperTrim( szAlias, pFileName->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH ); + pOpenInfo->atomAlias = ( BYTE * ) szAlias; + } + hb_xfree( pFileName ); + + /* Try open */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, uiFlags | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return FAILURE; + } + + hb_delimInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Retrieve information about the current driver. + */ +static ERRCODE hb_delimRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_delimRddInfo(%p,%hu,%lu,%p)", pRDD, uiIndex, ulConnect, pItem)); + + switch( uiIndex ) + { + case RDDI_CANPUTREC: + case RDDI_LOCAL: + case RDDI_LARGEFILE: + hb_itemPutL( pItem, TRUE ); + break; + + case RDDI_TABLEEXT: + hb_itemPutC( pItem, DELIM_TABLEEXT ); + break; + + default: + return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem ); + + } + + return SUCCESS; +} + + +static RDDFUNCS delimTable = { NULL /* hb_delimBof */, + NULL /* hb_delimEof */, + NULL /* hb_delimFound */, + NULL /* hb_delimGoBottom */, + NULL /* hb_delimGoTo */, + NULL /* hb_delimGoToId */, + ( DBENTRYP_V ) hb_delimGoTop, + NULL /* hb_delimSeek */, + NULL /* hb_delimSkip */, + NULL /* hb_delimSkipFilter */, + ( DBENTRYP_L ) hb_delimSkipRaw, + ( DBENTRYP_VF ) hb_delimAddField, + ( DBENTRYP_B ) hb_delimAppend, + NULL /* hb_delimCreateFields */, + ( DBENTRYP_V ) hb_delimDeleteRec, + ( DBENTRYP_BP ) hb_delimDeleted, + NULL /* hb_delimFieldCount */, + NULL /* hb_delimFieldDisplay */, + NULL /* hb_delimFieldInfo */, + NULL /* hb_delimFieldName */, + ( DBENTRYP_V ) hb_delimFlush, + ( DBENTRYP_PP ) hb_delimGetRec, + ( DBENTRYP_SI ) hb_delimGetValue, + NULL /* hb_delimGetVarLen */, + ( DBENTRYP_V ) hb_delimGoCold, + ( DBENTRYP_V ) hb_delimGoHot, + ( DBENTRYP_P ) hb_delimPutRec, + ( DBENTRYP_SI ) hb_delimPutValue, + NULL /* hb_delimRecall */, + ( DBENTRYP_ULP ) hb_delimRecCount, + NULL /* hb_delimRecInfo */, + ( DBENTRYP_ULP ) hb_delimRecNo, + ( DBENTRYP_I ) hb_delimRecId, + ( DBENTRYP_S ) hb_delimSetFieldExtent, + NULL /* hb_delimAlias */, + ( DBENTRYP_V ) hb_delimClose, + ( DBENTRYP_VP ) hb_delimCreate, + ( DBENTRYP_SI ) hb_delimInfo, + ( DBENTRYP_V ) hb_delimNewArea, + ( DBENTRYP_VP ) hb_delimOpen, + NULL /* hb_delimRelease */, + ( DBENTRYP_SP ) hb_delimStructSize, + NULL /* hb_delimSysName */, + NULL /* hb_delimEval */, + NULL /* hb_delimPack */, + NULL /* hb_delimPackRec */, + NULL /* hb_delimSort */, + ( DBENTRYP_VT ) hb_delimTrans, + NULL /* hb_delimTransRec */, + NULL /* hb_delimZap */, + NULL /* hb_delimChildEnd */, + NULL /* hb_delimChildStart */, + NULL /* hb_delimChildSync */, + NULL /* hb_delimSyncChildren */, + NULL /* hb_delimClearRel */, + NULL /* hb_delimForceRel */, + NULL /* hb_delimRelArea */, + NULL /* hb_delimRelEval */, + NULL /* hb_delimRelText */, + NULL /* hb_delimSetRel */, + NULL /* hb_delimOrderListAdd */, + NULL /* hb_delimOrderListClear */, + NULL /* hb_delimOrderListDelete */, + NULL /* hb_delimOrderListFocus */, + NULL /* hb_delimOrderListRebuild */, + NULL /* hb_delimOrderCondition */, + NULL /* hb_delimOrderCreate */, + NULL /* hb_delimOrderDestroy */, + NULL /* hb_delimOrderInfo */, + NULL /* hb_delimClearFilter */, + NULL /* hb_delimClearLocate */, + NULL /* hb_delimClearScope */, + NULL /* hb_delimCountScope */, + NULL /* hb_delimFilterText */, + NULL /* hb_delimScopeInfo */, + NULL /* hb_delimSetFilter */, + NULL /* hb_delimSetLocate */, + NULL /* hb_delimSetScope */, + NULL /* hb_delimSkipScope */, + NULL /* hb_delimLocate */, + NULL /* hb_delimCompile */, + NULL /* hb_delimError */, + NULL /* hb_delimEvalBlock */, + NULL /* hb_delimRawLock */, + NULL /* hb_delimLock */, + NULL /* hb_delimUnLock */, + NULL /* hb_delimCloseMemFile */, + NULL /* hb_delimCreateMemFile */, + NULL /* hb_delimGetValueFile */, + NULL /* hb_delimOpenMemFile */, + NULL /* hb_delimPutValueFile */, + NULL /* hb_delimReadDBHeader */, + NULL /* hb_delimWriteDBHeader */, + NULL /* hb_delimInit */, + NULL /* hb_delimExit */, + NULL /* hb_delimDrop */, + NULL /* hb_delimExists */, + ( DBENTRYP_RSLV ) hb_delimRddInfo, + NULL /* hb_delimWhoCares */ }; @@ -189,9 +1481,6 @@ HB_FUNC( DELIM_GETFUNCTABLE ) #define __PRG_SOURCE__ __FILE__ -HB_FUNC( DELIM ); -HB_FUNC( DELIM_GETFUNCTABLE ); - #ifdef HB_PCODE_VER #undef HB_PRG_PCODE_VER #define HB_PRG_PCODE_VER HB_PCODE_VER diff --git a/harbour/source/rdd/sdf1.c b/harbour/source/rdd/sdf1.c index 3869ebd400..697838a3e3 100644 --- a/harbour/source/rdd/sdf1.c +++ b/harbour/source/rdd/sdf1.c @@ -4,9 +4,9 @@ /* * Harbour Project source code: - * SDF RDD module + * SDF RDD * - * Copyright 1999 Bruno Cantero + * Copyright 2006 Przemyslaw Czerpak * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -53,120 +53,1180 @@ #include "hbapi.h" #include "hbinit.h" #include "hbvm.h" +#include "hbset.h" #include "hbapirdd.h" #include "hbapiitm.h" +#include "hbapilng.h" #include "hbapierr.h" +#include "hbdbferr.h" #include "hbrddsdf.h" #include "rddsys.ch" -static RDDFUNCS sdfSuper; -static RDDFUNCS sdfTable = { hb_sdfBof, - hb_sdfEof, - hb_sdfFound, - hb_sdfGoBottom, - hb_sdfGoTo, - hb_sdfGoToId, - hb_sdfGoTop, - hb_sdfSeek, - hb_sdfSkip, - hb_sdfSkipFilter, - hb_sdfSkipRaw, - hb_sdfAddField, - hb_sdfAppend, - hb_sdfCreateFields, - hb_sdfDeleteRec, - hb_sdfDeleted, - hb_sdfFieldCount, - hb_sdfFieldDisplay, - hb_sdfFieldInfo, - hb_sdfFieldName, - hb_sdfFlush, - hb_sdfGetRec, - hb_sdfGetValue, - hb_sdfGetVarLen, - hb_sdfGoCold, - hb_sdfGoHot, - hb_sdfPutRec, - hb_sdfPutValue, - hb_sdfRecall, - hb_sdfRecCount, - hb_sdfRecInfo, - hb_sdfRecNo, - hb_sdfRecId, - hb_sdfSetFieldExtent, - hb_sdfAlias, - hb_sdfClose, - hb_sdfCreate, - hb_sdfInfo, - hb_sdfNewArea, - hb_sdfOpen, - hb_sdfRelease, - hb_sdfStructSize, - hb_sdfSysName, - hb_sdfEval, - hb_sdfPack, - hb_sdfPackRec, - hb_sdfSort, - hb_sdfTrans, - hb_sdfTransRec, - hb_sdfZap, - hb_sdfChildEnd, - hb_sdfChildStart, - hb_sdfChildSync, - hb_sdfSyncChildren, - hb_sdfClearRel, - hb_sdfForceRel, - hb_sdfRelArea, - hb_sdfRelEval, - hb_sdfRelText, - hb_sdfSetRel, - hb_sdfOrderListAdd, - hb_sdfOrderListClear, - hb_sdfOrderListDelete, - hb_sdfOrderListFocus, - hb_sdfOrderListRebuild, - hb_sdfOrderCondition, - hb_sdfOrderCreate, - hb_sdfOrderDestroy, - hb_sdfOrderInfo, - hb_sdfClearFilter, - hb_sdfClearLocate, - hb_sdfClearScope, - hb_sdfCountScope, - hb_sdfFilterText, - hb_sdfScopeInfo, - hb_sdfSetFilter, - hb_sdfSetLocate, - hb_sdfSetScope, - hb_sdfSkipScope, - hb_sdfLocate, - hb_sdfCompile, - hb_sdfError, - hb_sdfEvalBlock, - hb_sdfRawLock, - hb_sdfLock, - hb_sdfUnLock, - hb_sdfCloseMemFile, - hb_sdfCreateMemFile, - hb_sdfGetValueFile, - hb_sdfOpenMemFile, - hb_sdfPutValueFile, - hb_sdfReadDBHeader, - hb_sdfWriteDBHeader, - hb_sdfInit, - hb_sdfExit, - hb_sdfDrop, - hb_sdfExists, - hb_sdfRddInfo, - hb_sdfWhoCares - }; +#define SUPERTABLE (&sdfSuper) +static RDDFUNCS sdfSuper; +static USHORT s_uiNumLength[ 9 ] = { 0, 4, 6, 8, 11, 13, 16, 18, 20 }; + +static void hb_sdfInitArea( SDFAREAP pArea, char * szFileName ) +{ + /* Allocate only after succesfully open file */ + pArea->szFileName = hb_strdup( szFileName ); + +#ifdef __XHARBOUR__ + if( hb_itemGetCLen( hb_set.HB_SET_EOL ) == 0 ) + pArea->szEol = hb_strdup( hb_conNewLine() ); + else + pArea->szEol = hb_strdup( hb_itemGetCPtr( hb_set.HB_SET_EOL ) ); +#else + pArea->szEol = hb_strdup( hb_conNewLine() ); +#endif + pArea->uiEolLen = strlen( pArea->szEol ); + + /* Alloc buffer */ + pArea->pRecord = ( BYTE * ) hb_xgrab( pArea->uiRecordLen + pArea->uiEolLen + 3 ); + /* pseudo deleted flag */ + *pArea->pRecord++ = ' '; + + pArea->ulFileSize = 0; + pArea->ulRecCount = 0; +} + +static void hb_sdfClearRecordBuffer( SDFAREAP pArea ) +{ + memset( pArea->pRecord, ' ', pArea->uiRecordLen ); + memcpy( pArea->pRecord + pArea->uiRecordLen, + pArea->szEol, pArea->uiEolLen ); +} + +static ERRCODE hb_sdfReadRecord( SDFAREAP pArea ) +{ + USHORT uiRead, uiToRead, uiEolPos; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfReadRecord(%p)", pArea)); + + uiToRead = pArea->uiRecordLen + pArea->uiEolLen + 2; + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + uiRead = hb_fsRead( pArea->hFile, pArea->pRecord, uiToRead ); + + if( uiRead > 0 && uiRead < uiToRead && pArea->pRecord[ uiRead - 1 ] == '\032' ) + --uiRead; + + if( uiRead == 0 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_sdfClearRecordBuffer( pArea ); + } + else + { + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + uiEolPos = hb_strAt( pArea->szEol, pArea->uiEolLen, + ( char * ) pArea->pRecord, uiRead ); + if( uiEolPos ) + { + --uiEolPos; + if( uiRead == pArea->uiRecordLen + pArea->uiEolLen ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = pArea->ulRecordOffset + uiEolPos + pArea->uiEolLen; + + if( uiEolPos < pArea->uiRecordLen ) + memset( pArea->pRecord + uiEolPos, ' ', pArea->uiRecordLen - uiEolPos ); + } + else + { + if( uiRead < uiToRead ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = 0; + + if( uiRead < pArea->uiRecordLen ) + memset( pArea->pRecord + uiRead, ' ', pArea->uiRecordLen - uiRead ); + } + + if( uiEolPos != pArea->uiRecordLen ) + memcpy( pArea->pRecord + pArea->uiRecordLen, + pArea->szEol, pArea->uiEolLen ); + } + + return SUCCESS; +} + +static ERRCODE hb_sdfNextRecord( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfNextRecord(%p)", pArea)); + + if( !pArea->fPositioned ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + { + if( pArea->ulNextOffset == 0 ) + { + USHORT uiRead, uiToRead, uiEolPos, uiRest = 0; + HB_FOFFSET ulOffset = 0; + + uiToRead = pArea->uiRecordLen + pArea->uiEolLen + 2; + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + + do + { + uiRead = hb_fsRead( pArea->hFile, pArea->pRecord + uiRest, + uiToRead - uiRest ) + uiRest; + if( uiRead > 0 && uiRead < uiToRead && + pArea->pRecord[ uiRead - 1 ] == '\032' ) + --uiRead; + + uiEolPos = hb_strAt( pArea->szEol, pArea->uiEolLen, + ( char * ) pArea->pRecord, uiRead ); + if( uiEolPos ) + { + --uiEolPos; + if( uiRead == pArea->uiRecordLen + pArea->uiEolLen ) + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + else + pArea->ulNextOffset = pArea->ulRecordOffset + ulOffset + + uiEolPos + pArea->uiEolLen; + } + else if( uiRead < uiToRead ) + { + pArea->ulNextOffset = ( HB_FOFFSET ) -1; + } + else + { + if( pArea->uiEolLen > 1 ) + { + uiRest = pArea->uiEolLen - 1; + memcpy( pArea->pRecord, pArea->pRecord + uiRead - uiRest, uiRest ); + } + ulOffset += uiRead - uiRest; + } + } + while( pArea->ulNextOffset == 0 ); + } + pArea->ulRecNo++; + } + + if( pArea->ulNextOffset == ( HB_FOFFSET ) -1 ) + { + pArea->fEof = TRUE; + pArea->fPositioned = FALSE; + hb_sdfClearRecordBuffer( pArea ); + return SUCCESS; + } + + pArea->ulRecordOffset = pArea->ulNextOffset; + return hb_sdfReadRecord( pArea ); +} /* * -- SDF METHODS -- */ +/* + * Position cursor at the first record. + */ +static ERRCODE hb_sdfGoTop( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoTop(%p)", pArea)); + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->fTop = TRUE; + pArea->fBottom = FALSE; + + pArea->ulRecordOffset = 0; + pArea->ulRecNo = 1; + if( hb_sdfReadRecord( pArea ) != SUCCESS ) + return FAILURE; + + return SELF_SKIPFILTER( ( AREAP ) pArea, 1 ); +} + +/* + * Reposition cursor, regardless of filter. + */ +static ERRCODE hb_sdfSkipRaw( SDFAREAP pArea, LONG lToSkip ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfSkipRaw(%p,%ld)", pArea, lToSkip)); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( lToSkip != 1 ) + return FAILURE; + else + return hb_sdfNextRecord( pArea ); +} + +/* + * Determine deleted status for a record. + */ +static ERRCODE hb_sdfDeleted( SDFAREAP pArea, BOOL * pDeleted ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfDeleted(%p,%p)", pArea, pDeleted)); + + HB_SYMBOL_UNUSED( pArea ); + + * pDeleted = FALSE; + + return SUCCESS; +} + +/* + * Obtain number of records in WorkArea. + */ +static ERRCODE hb_sdfRecCount( SDFAREAP pArea, ULONG * pRecCount ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecCount(%p,%p)", pArea, pRecCount)); + + * pRecCount = pArea->ulRecCount; + return SUCCESS; +} + +/* + * Obtain physical row number at current WorkArea cursor position. + */ +static ERRCODE hb_sdfRecNo( SDFAREAP pArea, ULONG * pulRecNo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecNo(%p,%p)", pArea, pulRecNo)); + + *pulRecNo = pArea->ulRecNo; + return SUCCESS; +} + +/* + * Obtain physical row ID at current WorkArea cursor position. + */ +static ERRCODE hb_sdfRecId( SDFAREAP pArea, PHB_ITEM pRecNo ) +{ + ERRCODE errCode; + ULONG ulRecNo; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRecId(%p,%p)", pArea, pRecNo)); + + errCode = SELF_RECNO( ( AREAP ) pArea, &ulRecNo ); + +#ifdef HB_C52_STRICT + /* this is for strict Clipper compatibility but IMHO Clipper should not + do that and always set fixed size independent to the record number */ + if( ulRecNo < 10000000 ) + { + hb_itemPutNLLen( pRecNo, ulRecNo, 7 ); + } + else + { + hb_itemPutNLLen( pRecNo, ulRecNo, 10 ); + } +#else + hb_itemPutNInt( pRecNo, ulRecNo ); +#endif + return errCode; +} + +/* + * Append a record to the WorkArea. + */ +static ERRCODE hb_sdfAppend( SDFAREAP pArea, BOOL fUnLockAll ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfAppend(%p,%d)", pArea, (int) fUnLockAll)); + + HB_SYMBOL_UNUSED( fUnLockAll ); + + if( SELF_GOCOLD( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + if( SELF_GOHOT( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->ulRecordOffset = pArea->ulFileSize; + pArea->ulRecNo = ++pArea->ulRecCount; + pArea->fEof = FALSE; + pArea->fPositioned = TRUE; + hb_sdfClearRecordBuffer( pArea ); + + return SUCCESS; +} + +/* + * Delete a record. + */ +static ERRCODE hb_sdfDeleteRec( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfDeleteRec(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + pArea->ulRecCount--; + pArea->fEof = TRUE; + pArea->fPositioned = pArea->fRecordChanged = FALSE; + hb_sdfClearRecordBuffer( pArea ); + } + + return SUCCESS; +} + +/* + * Obtain the current value of a field. + */ +static ERRCODE hb_sdfGetValue( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + LPFIELD pField; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGetValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + + --uiIndex; + pField = pArea->lpFields + uiIndex; + switch( pField->uiType ) + { + case HB_IT_STRING: +#ifndef HB_CDP_SUPPORT_OFF + if( pArea->cdPage != hb_cdp_page ) + { + char * pVal = ( char * ) hb_xgrab( pField->uiLen + 1 ); + memcpy( pVal, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], pField->uiLen ); + pVal[ pField->uiLen ] = '\0'; + hb_cdpnTranslate( pVal, pArea->cdPage, hb_cdp_page, pField->uiLen ); + hb_itemPutCPtr( pItem, pVal, pField->uiLen ); + } + else +#endif + { + hb_itemPutCL( pItem, ( char * ) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen ); + } + break; + + case HB_IT_LOGICAL: + switch( pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] ) + { + case 'T': + case 't': + case 'Y': + case 'y': + hb_itemPutL( pItem, TRUE ); + break; + default: + hb_itemPutL( pItem, FALSE ); + break; + } + break; + + case HB_IT_DATE: + { + char szBuffer[ 9 ]; + memcpy( szBuffer, pArea->pRecord + pArea->pFieldOffset[ uiIndex ], 8 ); + szBuffer[ 8 ] = 0; + hb_itemPutDS( pItem, szBuffer ); + } + break; + + case HB_IT_LONG: + { + HB_LONG lVal; + double dVal; + BOOL fDbl; + + fDbl = hb_strnToNum( (const char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + pField->uiLen, &lVal, &dVal ); + + if( pField->uiDec ) + { + hb_itemPutNDLen( pItem, fDbl ? dVal : ( double ) lVal, + ( int ) ( pField->uiLen - pField->uiDec - 1 ), + ( int ) pField->uiDec ); + } + else if( fDbl ) + { + hb_itemPutNDLen( pItem, dVal, ( int ) pField->uiLen, 0 ); + } + else + { + hb_itemPutNIntLen( pItem, lVal, ( int ) pField->uiLen ); + } + } + break; + + case HB_IT_MEMO: + hb_itemPutC( pItem, "" ); + break; + + default: + { + PHB_ITEM pError; + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_DATATYPE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_DATATYPE ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, EDBF_DATATYPE ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + } + + return SUCCESS; +} + +/* + * Assign a value to a field. + */ +static ERRCODE hb_sdfPutValue( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + char szBuffer[ 256 ]; + ERRCODE uiError; + LPFIELD pField; + USHORT uiSize; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfPutValue(%p,%hu,%p)", pArea, uiIndex, pItem)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + uiError = SUCCESS; + --uiIndex; + pField = pArea->lpFields + uiIndex; + if( pField->uiType != HB_IT_MEMO ) + { + if( HB_IS_MEMO( pItem ) || HB_IS_STRING( pItem ) ) + { + if( pField->uiType == HB_IT_STRING ) + { + uiSize = ( USHORT ) hb_itemGetCLen( pItem ); + if( uiSize > pField->uiLen ) + uiSize = pField->uiLen; + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + hb_itemGetCPtr( pItem ), uiSize ); +#ifndef HB_CDP_SUPPORT_OFF + hb_cdpnTranslate( (char *) pArea->pRecord + pArea->pFieldOffset[ uiIndex ], hb_cdp_page, pArea->cdPage, uiSize ); +#endif + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ] + uiSize, + ' ', pField->uiLen - uiSize ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_DATE( pItem ) ) + { + if( pField->uiType == HB_IT_DATE ) + { + hb_itemGetDS( pItem, szBuffer ); + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], szBuffer, 8 ); + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_NUMBER( pItem ) ) + { + if( pField->uiType == HB_IT_LONG ) + { + if( hb_itemStrBuf( szBuffer, pItem, pField->uiLen, pField->uiDec ) ) + { + memcpy( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + szBuffer, pField->uiLen ); + } + else + { + uiError = EDBF_DATAWIDTH; + memset( pArea->pRecord + pArea->pFieldOffset[ uiIndex ], + '*', pField->uiLen ); + } + } + else + uiError = EDBF_DATATYPE; + } + else if( HB_IS_LOGICAL( pItem ) ) + { + if( pField->uiType == HB_IT_LOGICAL ) + pArea->pRecord[ pArea->pFieldOffset[ uiIndex ] ] = hb_itemGetL( pItem ) ? 'T' : 'F'; + else + uiError = EDBF_DATATYPE; + } + else + uiError = EDBF_DATATYPE; + } + + if( uiError != SUCCESS ) + { + PHB_ITEM pError= hb_errNew(); + USHORT uiGenCode = uiError == EDBF_DATAWIDTH ? EG_DATAWIDTH : EDBF_DATATYPE; + + hb_errPutGenCode( pError, uiGenCode ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( uiGenCode ) ); + hb_errPutOperation( pError, hb_dynsymName( ( PHB_DYNS ) pField->sym ) ); + hb_errPutSubCode( pError, uiError ); + hb_errPutFlags( pError, EF_CANDEFAULT ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return SUCCESS; + /* return FAILURE; */ + } + + return SUCCESS; +} + +/* + * Replace the current record. + */ +static ERRCODE hb_sdfPutRec( SDFAREAP pArea, BYTE * pBuffer ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfPutRec(%p,%p)", pArea, pBuffer)); + + if( !pArea->fPositioned ) + return SUCCESS; + + if( !pArea->fRecordChanged ) + return FAILURE; + + /* Copy data to buffer */ + memcpy( pArea->pRecord, pBuffer + 1, pArea->uiRecordLen ); + + return SUCCESS; +} + +/* + * Retrieve current record buffer + */ +static ERRCODE hb_sdfGetRec( SDFAREAP pArea, BYTE ** pBufferPtr ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGetRec(%p,%p)", pArea, pBufferPtr)); + + *pBufferPtr = pArea->pRecord - 1; + + return SUCCESS; +} + +/* + * Copy one or more records from one WorkArea to another. + */ +static ERRCODE hb_sdfTrans( SDFAREAP pArea, LPDBTRANSINFO pTransInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfTrans(%p, %p)", pArea, pTransInfo)); + + if( pTransInfo->uiFlags & DBTF_MATCH ) + { + if( !pArea->fTransRec || pArea->cdPage != pTransInfo->lpaDest->cdPage ) + pTransInfo->uiFlags &= ~DBTF_PUTREC; + else if( pArea->rddID == pTransInfo->lpaDest->rddID ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + { + PHB_ITEM pPutRec = hb_itemPutL( NULL, FALSE ); + SELF_INFO( ( AREAP ) pTransInfo->lpaDest, DBI_CANPUTREC, pPutRec ); + if( hb_itemGetL( pPutRec ) ) + pTransInfo->uiFlags |= DBTF_PUTREC; + else + pTransInfo->uiFlags &= ~DBTF_PUTREC; + hb_itemRelease( pPutRec ); + } + } + return SUPER_TRANS( ( AREAP ) pArea, pTransInfo ); +} + +/* + * Perform a write of WorkArea memory to the data store. + */ +static ERRCODE hb_sdfGoCold( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoCold(%p)", pArea)); + + if( pArea->fRecordChanged ) + { + USHORT uiWrite = pArea->uiRecordLen + pArea->uiEolLen; + + hb_fsSeekLarge( pArea->hFile, pArea->ulRecordOffset, FS_SET ); + if( hb_fsWrite( pArea->hFile, pArea->pRecord, uiWrite ) != uiWrite ) + { + PHB_ITEM pError = hb_errNew(); + + hb_errPutGenCode( pError, EG_WRITE ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_WRITE ) ); + hb_errPutSubCode( pError, EDBF_WRITE ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutFileName( pError, pArea->szFileName ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->ulFileSize += uiWrite; + pArea->ulNextOffset = pArea->ulFileSize; + pArea->fRecordChanged = FALSE; + pArea->fFlush = TRUE; + } + return SUCCESS; +} + +/* + * Mark the WorkArea data buffer as hot. + */ +static ERRCODE hb_sdfGoHot( SDFAREAP pArea ) +{ + PHB_ITEM pError; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfGoHot(%p)", pArea)); + + if( pArea->fReadonly ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_READONLY ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_READONLY ) ); + hb_errPutSubCode( pError, EDBF_READONLY ); + SELF_ERROR( ( AREAP ) pArea, pError ); + hb_itemRelease( pError ); + return FAILURE; + } + pArea->fRecordChanged = TRUE; + return SUCCESS; +} + +/* + * Write data buffer to the data store. + */ +static ERRCODE hb_sdfFlush( SDFAREAP pArea ) +{ + ERRCODE uiError; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfFlush(%p)", pArea)); + + uiError = SELF_GOCOLD( ( AREAP ) pArea ); + + if( pArea->fFlush ) + { + hb_fsSeekLarge( pArea->hFile, pArea->ulFileSize, FS_SET ); + hb_fsWrite( pArea->hFile, ( BYTE * ) "\032", 1 ); + if( hb_set.HB_SET_HARDCOMMIT ) + { + hb_fsCommit( pArea->hFile ); + pArea->fFlush = FALSE; + } + } + + return uiError; +} + +/* + * Retrieve information about the current table/driver. + */ +static ERRCODE hb_sdfInfo( SDFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfInfo(%p,%hu,%p)", pArea, uiIndex, pItem)); + + switch( uiIndex ) + { + case DBI_CANPUTREC: + hb_itemPutL( pItem, pArea->fTransRec ); + break; + + case DBI_GETRECSIZE: + hb_itemPutNL( pItem, pArea->uiRecordLen ); + break; + + case DBI_FULLPATH: + hb_itemPutC( pItem, pArea->szFileName); + break; + + case DBI_FILEHANDLE: + hb_itemPutNInt( pItem, ( HB_LONG ) pArea->hFile ); + break; + + case DBI_SHARED: + hb_itemPutL( pItem, pArea->fShared ); + break; + + case DBI_ISREADONLY: + hb_itemPutL( pItem, pArea->fReadonly ); + break; + + case DBI_DB_VERSION: + case DBI_RDD_VERSION: + { + char szBuf[ 64 ]; + int iSub = hb_itemGetNI( pItem ); + + if( iSub == 1 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s)", 0, 1, "SDF" ); + else if( iSub == 2 ) + snprintf( szBuf, sizeof( szBuf ), "%d.%d (%s:%d)", 0, 1, "SDF", pArea->rddID ); + else + snprintf( szBuf, sizeof( szBuf ), "%d.%d", 0, 1 ); + hb_itemPutC( pItem, szBuf ); + break; + } + + default: + return SUPER_INFO( ( AREAP ) pArea, uiIndex, pItem ); + } + + return SUCCESS; +} + +/* + * Add a field to the WorkArea. + */ +static ERRCODE hb_sdfAddField( SDFAREAP pArea, LPDBFIELDINFO pFieldInfo ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfAddField(%p, %p)", pArea, pFieldInfo)); + + switch( pFieldInfo->uiType ) + { + case HB_IT_MEMO: + pFieldInfo->uiLen = 0; + pArea->fTransRec = FALSE; + break; + + case HB_IT_ANY: + if( pFieldInfo->uiLen == 3 ) + { + pFieldInfo->uiType = HB_IT_DATE; + pFieldInfo->uiLen = 8; + } + else if( pFieldInfo->uiLen < 6 ) + { + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + } + else + { + pFieldInfo->uiType = HB_IT_MEMO; + pFieldInfo->uiLen = 0; + } + pArea->fTransRec = FALSE; + break; + + case HB_IT_DATE: + if( pFieldInfo->uiLen != 8 ) + { + pFieldInfo->uiLen = 8; + pArea->fTransRec = FALSE; + } + break; + + case HB_IT_INTEGER: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = s_uiNumLength[ pFieldInfo->uiLen ]; + pArea->fTransRec = FALSE; + break; + + case HB_IT_DOUBLE: + pFieldInfo->uiType = HB_IT_LONG; + pFieldInfo->uiLen = 20; + pArea->fTransRec = FALSE; + break; + } + + /* Update field offset */ + pArea->pFieldOffset[ pArea->uiFieldCount ] = pArea->uiRecordLen; + pArea->uiRecordLen += pFieldInfo->uiLen; + + return SUPER_ADDFIELD( ( AREAP ) pArea, pFieldInfo ); +} + +/* + * Establish the extent of the array of fields for a WorkArea. + */ +static ERRCODE hb_sdfSetFieldExtent( SDFAREAP pArea, USHORT uiFieldExtent ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfSetFieldExtent(%p,%hu)", pArea, uiFieldExtent)); + + if( SUPER_SETFIELDEXTENT( ( AREAP ) pArea, uiFieldExtent ) == FAILURE ) + return FAILURE; + + /* Alloc field offsets array */ + if( uiFieldExtent ) + { + pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT ) ); + memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT ) ); + } + + return SUCCESS; +} + +/* + * Clear the WorkArea for use. + */ +static ERRCODE hb_sdfNewArea( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfNewArea(%p)", pArea)); + + if( SUPER_NEW( ( AREAP ) pArea ) == FAILURE ) + return FAILURE; + + pArea->hFile = FS_ERROR; + pArea->fTransRec = TRUE; + pArea->uiRecordLen = 0; + + return SUCCESS; +} + +/* + * Retrieve the size of the WorkArea structure. + */ +static ERRCODE hb_sdfStructSize( SDFAREAP pArea, USHORT * uiSize ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfStrucSize(%p,%p)", pArea, uiSize)); + HB_SYMBOL_UNUSED( pArea ); + + * uiSize = sizeof( SDFAREA ); + return SUCCESS; +} + +/* + * Close the table in the WorkArea. + */ +static ERRCODE hb_sdfClose( SDFAREAP pArea ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfClose(%p)", pArea)); + + SUPER_CLOSE( ( AREAP ) pArea ); + + /* Update record and unlock records */ + if( pArea->hFile != FS_ERROR ) + { + SELF_FLUSH( ( AREAP ) pArea ); + hb_fsClose( pArea->hFile ); + pArea->hFile = FS_ERROR; + } + + if( pArea->pFieldOffset ) + { + hb_xfree( pArea->pFieldOffset ); + pArea->pFieldOffset = NULL; + } + if( pArea->pRecord ) + { + hb_xfree( pArea->pRecord - 1 ); + pArea->pRecord = NULL; + } + if( pArea->szEol ) + { + hb_xfree( pArea->szEol ); + pArea->szEol = NULL; + } + if( pArea->szFileName ) + { + hb_xfree( pArea->szFileName ); + pArea->szFileName = NULL; + } + + return SUCCESS; +} + +/* + * Create a data store in the specified WorkArea. + */ +static ERRCODE hb_sdfCreate( SDFAREAP pArea, LPDBOPENINFO pCreateInfo ) +{ + ERRCODE errCode = SUCCESS; + PHB_FNAME pFileName; + PHB_ITEM pError = NULL; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfCreate(%p,%p)", pArea, pCreateInfo)); + + pArea->fShared = FALSE; /* pCreateInfo->fShared; */ + pArea->fReadonly = FALSE; /* pCreateInfo->fReadonly */ +#ifndef HB_CDP_SUPPORT_OFF + if( pCreateInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pCreateInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + pFileName = hb_fsFNameSplit( ( char * ) pCreateInfo->abName ); + if( ! pFileName->szExtension ) + { + PHB_ITEM pItem = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pItem ); + pFileName->szExtension = hb_itemGetCPtr( pItem ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pItem ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pCreateInfo->abName, _POSIX_PATH_MAX ); + } + hb_xfree( pFileName ); + + /* Try create */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, + FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_CREATE ); + hb_errPutSubCode( pError, EDBF_CREATE_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_CREATE( ( AREAP ) pArea, pCreateInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return errCode; + } + + hb_sdfInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Open a data store in the WorkArea. + */ +static ERRCODE hb_sdfOpen( SDFAREAP pArea, LPDBOPENINFO pOpenInfo ) +{ + PHB_ITEM pError = NULL; + PHB_FNAME pFileName; + ERRCODE errCode; + USHORT uiFlags; + BOOL fRetry; + BYTE szFileName[ _POSIX_PATH_MAX + 1 ]; + char szAlias[ HARBOUR_MAX_RDD_ALIAS_LENGTH + 1 ]; + + HB_TRACE(HB_TR_DEBUG, ("hb_sdfOpen(%p,%p)", pArea, pOpenInfo)); + + pArea->fShared = TRUE; /* pOpenInfo->fShared; */ + pArea->fReadonly = TRUE; /* pOpenInfo->fReadonly; */ +#ifndef HB_CDP_SUPPORT_OFF + if( pOpenInfo->cdpId ) + { + pArea->cdPage = hb_cdpFind( (char *) pOpenInfo->cdpId ); + if( !pArea->cdPage ) + pArea->cdPage = hb_cdp_page; + } + else + pArea->cdPage = hb_cdp_page; +#endif + + uiFlags = ( pArea->fReadonly ? FO_READ : FO_READWRITE ) | + ( pArea->fShared ? FO_DENYNONE : FO_EXCLUSIVE ); + + pFileName = hb_fsFNameSplit( ( char * ) pOpenInfo->abName ); + /* Add default file name extension if necessary */ + if( ! pFileName->szExtension ) + { + PHB_ITEM pFileExt = hb_itemPutC( NULL, "" ); + SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pFileExt ); + pFileName->szExtension = hb_itemGetCPtr( pFileExt ); + hb_fsFNameMerge( ( char * ) szFileName, pFileName ); + hb_itemRelease( pFileExt ); + } + else + { + hb_strncpy( ( char * ) szFileName, ( char * ) pOpenInfo->abName, _POSIX_PATH_MAX ); + } + + /* Create default alias if necessary */ + if( !pOpenInfo->atomAlias && pFileName->szName ) + { + hb_strncpyUpperTrim( szAlias, pFileName->szName, HARBOUR_MAX_RDD_ALIAS_LENGTH ); + pOpenInfo->atomAlias = ( BYTE * ) szAlias; + } + hb_xfree( pFileName ); + + /* Try open */ + do + { + pArea->hFile = hb_fsExtOpen( szFileName, NULL, uiFlags | + FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME, + NULL, pError ); + if( pArea->hFile == FS_ERROR ) + { + if( !pError ) + { + pError = hb_errNew(); + hb_errPutGenCode( pError, EG_OPEN ); + hb_errPutSubCode( pError, EDBF_OPEN_DBF ); + hb_errPutOsCode( pError, hb_fsError() ); + hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) ); + hb_errPutFileName( pError, ( char * ) szFileName ); + hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT ); + } + fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY ); + } + else + fRetry = FALSE; + } + while( fRetry ); + + if( pError ) + hb_itemRelease( pError ); + + if( pArea->hFile == FS_ERROR ) + return FAILURE; + + errCode = SUPER_OPEN( ( AREAP ) pArea, pOpenInfo ); + if( errCode != SUCCESS ) + { + SELF_CLOSE( ( AREAP ) pArea ); + return FAILURE; + } + + hb_sdfInitArea( pArea, ( char * ) szFileName ); + + /* Position cursor at the first record */ + return SELF_GOTOP( ( AREAP ) pArea ); +} + +/* + * Retrieve information about the current driver. + */ +static ERRCODE hb_sdfRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, PHB_ITEM pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_sdfRddInfo(%p,%hu,%lu,%p)", pRDD, uiIndex, ulConnect, pItem)); + + switch( uiIndex ) + { + case RDDI_CANPUTREC: + case RDDI_LOCAL: + case RDDI_LARGEFILE: + hb_itemPutL( pItem, TRUE ); + break; + + case RDDI_TABLEEXT: + hb_itemPutC( pItem, SDF_TABLEEXT ); + break; + + default: + return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem ); + + } + + return SUCCESS; +} + + +static RDDFUNCS sdfTable = { NULL /* hb_sdfBof */, + NULL /* hb_sdfEof */, + NULL /* hb_sdfFound */, + NULL /* hb_sdfGoBottom */, + NULL /* hb_sdfGoTo */, + NULL /* hb_sdfGoToId */, + ( DBENTRYP_V ) hb_sdfGoTop, + NULL /* hb_sdfSeek */, + NULL /* hb_sdfSkip */, + NULL /* hb_sdfSkipFilter */, + ( DBENTRYP_L ) hb_sdfSkipRaw, + ( DBENTRYP_VF ) hb_sdfAddField, + ( DBENTRYP_B ) hb_sdfAppend, + NULL /* hb_sdfCreateFields */, + ( DBENTRYP_V ) hb_sdfDeleteRec, + ( DBENTRYP_BP ) hb_sdfDeleted, + NULL /* hb_sdfFieldCount */, + NULL /* hb_sdfFieldDisplay */, + NULL /* hb_sdfFieldInfo */, + NULL /* hb_sdfFieldName */, + ( DBENTRYP_V ) hb_sdfFlush, + ( DBENTRYP_PP ) hb_sdfGetRec, + ( DBENTRYP_SI ) hb_sdfGetValue, + NULL /* hb_sdfGetVarLen */, + ( DBENTRYP_V ) hb_sdfGoCold, + ( DBENTRYP_V ) hb_sdfGoHot, + ( DBENTRYP_P ) hb_sdfPutRec, + ( DBENTRYP_SI ) hb_sdfPutValue, + NULL /* hb_sdfRecall */, + ( DBENTRYP_ULP ) hb_sdfRecCount, + NULL /* hb_sdfRecInfo */, + ( DBENTRYP_ULP ) hb_sdfRecNo, + ( DBENTRYP_I ) hb_sdfRecId, + ( DBENTRYP_S ) hb_sdfSetFieldExtent, + NULL /* hb_sdfAlias */, + ( DBENTRYP_V ) hb_sdfClose, + ( DBENTRYP_VP ) hb_sdfCreate, + ( DBENTRYP_SI ) hb_sdfInfo, + ( DBENTRYP_V ) hb_sdfNewArea, + ( DBENTRYP_VP ) hb_sdfOpen, + NULL /* hb_sdfRelease */, + ( DBENTRYP_SP ) hb_sdfStructSize, + NULL /* hb_sdfSysName */, + NULL /* hb_sdfEval */, + NULL /* hb_sdfPack */, + NULL /* hb_sdfPackRec */, + NULL /* hb_sdfSort */, + ( DBENTRYP_VT ) hb_sdfTrans, + NULL /* hb_sdfTransRec */, + NULL /* hb_sdfZap */, + NULL /* hb_sdfChildEnd */, + NULL /* hb_sdfChildStart */, + NULL /* hb_sdfChildSync */, + NULL /* hb_sdfSyncChildren */, + NULL /* hb_sdfClearRel */, + NULL /* hb_sdfForceRel */, + NULL /* hb_sdfRelArea */, + NULL /* hb_sdfRelEval */, + NULL /* hb_sdfRelText */, + NULL /* hb_sdfSetRel */, + NULL /* hb_sdfOrderListAdd */, + NULL /* hb_sdfOrderListClear */, + NULL /* hb_sdfOrderListDelete */, + NULL /* hb_sdfOrderListFocus */, + NULL /* hb_sdfOrderListRebuild */, + NULL /* hb_sdfOrderCondition */, + NULL /* hb_sdfOrderCreate */, + NULL /* hb_sdfOrderDestroy */, + NULL /* hb_sdfOrderInfo */, + NULL /* hb_sdfClearFilter */, + NULL /* hb_sdfClearLocate */, + NULL /* hb_sdfClearScope */, + NULL /* hb_sdfCountScope */, + NULL /* hb_sdfFilterText */, + NULL /* hb_sdfScopeInfo */, + NULL /* hb_sdfSetFilter */, + NULL /* hb_sdfSetLocate */, + NULL /* hb_sdfSetScope */, + NULL /* hb_sdfSkipScope */, + NULL /* hb_sdfLocate */, + NULL /* hb_sdfCompile */, + NULL /* hb_sdfError */, + NULL /* hb_sdfEvalBlock */, + NULL /* hb_sdfRawLock */, + NULL /* hb_sdfLock */, + NULL /* hb_sdfUnLock */, + NULL /* hb_sdfCloseMemFile */, + NULL /* hb_sdfCreateMemFile */, + NULL /* hb_sdfGetValueFile */, + NULL /* hb_sdfOpenMemFile */, + NULL /* hb_sdfPutValueFile */, + NULL /* hb_sdfReadDBHeader */, + NULL /* hb_sdfWriteDBHeader */, + NULL /* hb_sdfInit */, + NULL /* hb_sdfExit */, + NULL /* hb_sdfDrop */, + NULL /* hb_sdfExists */, + ( DBENTRYP_RSLV ) hb_sdfRddInfo, + NULL /* hb_sdfWhoCares */ + }; HB_FUNC( SDF ) { ; } diff --git a/harbour/source/rdd/workarea.c b/harbour/source/rdd/workarea.c index c2e09f014a..feea968f6b 100644 --- a/harbour/source/rdd/workarea.c +++ b/harbour/source/rdd/workarea.c @@ -583,12 +583,13 @@ ERRCODE hb_waClose( AREAP pArea ) ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { HB_TRACE(HB_TR_DEBUG, ("hb_waInfo(%p, %hu, %p)", pArea, uiIndex, pItem)); - HB_SYMBOL_UNUSED( pArea ); switch ( uiIndex ) { case DBI_ISDBF: case DBI_CANPUTREC: + case DBI_ISFLOCK: + case DBI_SHARED: hb_itemPutL( pItem, FALSE ); break; @@ -601,6 +602,20 @@ ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) hb_itemPutC( pItem, "" ); return FAILURE; + case DBI_GETHEADERSIZE: + case DBI_GETRECSIZE: + case DBI_LOCKCOUNT: + hb_itemPutNI( pItem, 0 ); + break; + + case DBI_LASTUPDATE: + hb_itemPutDL( pItem, 0 ); + break; + + case DBI_GETLOCKARRAY: + hb_arrayNew( pItem, 0 ); + break; + case DBI_CHILDCOUNT: { LPDBRELINFO lpdbRelations = pArea->lpdbRelations; @@ -648,6 +663,10 @@ ERRCODE hb_waInfo( AREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) break; } + case DBI_TABLEEXT: + hb_itemClear( pItem ); + return SELF_RDDINFO( SELF_RDDNODE( pArea ), RDDI_TABLEEXT, 0, pItem ); + case DBI_SCOPEDRELATION: { int iRelNo = hb_itemGetNI( pItem ); diff --git a/harbour/source/rtl/dbdelim.prg b/harbour/source/rtl/dbdelim.prg index 57d559d041..e93ee72bd6 100644 --- a/harbour/source/rtl/dbdelim.prg +++ b/harbour/source/rtl/dbdelim.prg @@ -11,6 +11,10 @@ * www - http://www.harbour-project.org * APPEND FROM code submitted by Marco Braida * + * Copyright 2006 Przemyslaw Czerpak + * function __dbDelim() replaced by the new one which uses + * DELIM RDD I've just created + * * 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, or (at your option) @@ -52,6 +56,21 @@ * */ +REQUEST DELIM + +PROCEDURE __dbDelim( lExport, cFile, cDelimArg, aFields, bFor, bWhile, nNext, nRecord, lRest ) + + IF lExport + __dbCopy( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "DELIM", , , cDelimArg ) + ELSE + __dbApp( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "DELIM", , , cDelimArg ) + ENDIF + +RETURN + + +#ifdef __DBDELIM_OLD_CODE__ + #include "hbcommon.ch" #include "fileio.ch" #include "error.ch" @@ -368,3 +387,5 @@ for ii:=1 to nDBFfields FIELDPUT(ii,vRes) next return .T. + +#endif /* __DBDELIM_OLD_CODE__ */ diff --git a/harbour/source/rtl/dbsdf.prg b/harbour/source/rtl/dbsdf.prg index d64115692f..d1cac4184c 100644 --- a/harbour/source/rtl/dbsdf.prg +++ b/harbour/source/rtl/dbsdf.prg @@ -10,6 +10,10 @@ * Copyright 2001-2002 David G. Holm * www - http://www.harbour-project.org * + * Copyright 2006 Przemyslaw Czerpak + * function __dbSDF() replaced by the new one which uses + * SDF RDD I've just created + * * 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, or (at your option) @@ -58,6 +62,21 @@ HB_FILE_VER( "$Id$" ) +REQUEST SDF + +PROCEDURE __dbSDF( lExport, cFile, aFields, bFor, bWhile, nNext, nRecord, lRest ) + + IF lExport + __dbCopy( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" ) + ELSE + __dbApp( cFile, aFields, bFor, bWhile, nNext, nRecord, lRest, "SDF" ) + ENDIF + +RETURN + + +#ifdef __DBSDF_OLD_CODE__ + #define SkipEOL( handle ) FSEEK( handle, nEOLSize, FS_RELATIVE ) #define AppendEOL( handle ) FWRITE( handle, HB_OSNewLine() ) #define AppendEOF( handle ) FWRITE( handle, CHR( 26 ) ) @@ -287,3 +306,4 @@ STATIC FUNCTION FindEOL(fh) endif RETURN cResult +#endif /* __DBSDF_OLD_CODE__ */