|
|
/***************************************************************************/ /* DBASE.C - This is the module containing the code to read and write */ /* dBASE files. */ /* */ /* (C) Copyright 1993-96 - SYWARE, Inc. - All rights reserved */ /***************************************************************************/
#include "precomp.h"
#include "wbemidl.h"
#include "dbase.h"
#include <stdio.h>
#include <time.h>
#define s_lstrcpy(a, b) lstrcpy((LPSTR) a, (LPCSTR) b)
#define s_lstrcat(a, b) lstrcat((LPSTR) a, (LPCSTR) b)
#define s_lstrlen(a) lstrlen((LPCSTR) a)
#define s_lstrcmp(a, b) lstrcmp((LPCSTR) a, (LPCSTR) b)
/***************************************************************************/ #define FIRST_RECORD 0xFFFFFFFF
#define LAST_RECORD 0xFFFFFFFE
/***************************************************************************/
SWORD FAR PASCAL dBaseExtendedOpen(LPUSTR name, BOOL fReadOnly, UWORD extraColumns, LPDBASEFILE FAR *lpf) { /*
HFILE hf; UWORD columnCount; UWORD recordLen; HGLOBAL h; LPDBASEFILE f; UWORD i; UCHAR FAR * ptr; UCHAR fullname[DBASE_MAX_PATHNAME_SIZE+1];
// Get the filename
s_lstrcpy((char*)fullname, name); ptr = fullname + s_lstrlen((char*)fullname); while ((ptr != fullname) && (*ptr != PATH_SEPARATOR_CHAR) && (*ptr != ':') && (*ptr != '.')) ptr--; if (*ptr != '.') s_lstrcat((char*)fullname, ".dbf");
// Open the file
if (fReadOnly) hf = _lopen((LPCSTR)fullname, OF_READ); else hf = _lopen((LPCSTR)fullname, OF_READWRITE); if (hf == HFILE_ERROR) return DBASE_ERR_TABLEACCESSERROR;
//Figure out how many columns there are
if (HFILE_ERROR == _llseek(hf, DBASE_HEADER_SIZE_OFFSET, 0)) { _lclose(hf); return DBASE_ERR_CORRUPTFILE; } if (sizeof(UWORD) != _lread(hf, &columnCount, sizeof(UWORD))) { _lclose(hf); return DBASE_ERR_CORRUPTFILE; } columnCount = (columnCount - DBASE_HEADER_LENGTH - 1)/ DBASE_COLUMN_DESCR_LENGTH;
// Get record size
if (HFILE_ERROR == _llseek(hf, DBASE_RECORD_LENGTH_OFFSET, 0)) { _lclose(hf); return DBASE_ERR_CORRUPTFILE; } if (sizeof(UWORD) != _lread(hf, &recordLen, sizeof(UWORD))) { _lclose(hf); return DBASE_ERR_CORRUPTFILE; }
// Allocate space for handle
h = GlobalAlloc (GMEM_MOVEABLE, (sizeof(DBASEFILE) - sizeof(DBASECOL)) + (sizeof(DBASECOL) * (columnCount + extraColumns)) + recordLen); if (h == NULL || (f = (LPDBASEFILE)GlobalLock (h)) == NULL) { _lclose(hf); return DBASE_ERR_MEMALLOCFAIL; }
// Read in the header
if (HFILE_ERROR == _llseek(hf, 0, 0)) { GlobalUnlock(h); GlobalFree(h); _lclose(hf); return DBASE_ERR_CORRUPTFILE; } if (DBASE_HEADER_LENGTH != _lread(hf, f, DBASE_HEADER_LENGTH)) { GlobalUnlock(h); GlobalFree(h); _lclose(hf); return DBASE_ERR_CORRUPTFILE; } if (f->encrypted != DBASE_NOT_ENCRYPTED) { GlobalUnlock(h); GlobalFree(h); _lclose(hf); return DBASE_ERR_CORRUPTFILE; } f->hf = hf; f->columnCount = columnCount; f->sortArray = NULL; f->currentRecord = 0; f->record = ((UCHAR FAR *) (&(f->column))) + ((columnCount+extraColumns) * sizeof(DBASECOL)); f->headerDirty = FALSE; f->recordDirty = FALSE; f->newRecord = FALSE;
// Read in column definition
ptr = f->record + 1; for (i = 0; (i < columnCount); i++) { if (DBASE_COLUMN_DESCR_LENGTH != _lread(hf, &(f->column[i]), DBASE_COLUMN_DESCR_LENGTH)) { GlobalUnlock(h); GlobalFree(h); _lclose(hf); return DBASE_ERR_CORRUPTFILE; } OemToAnsiBuff((LPCSTR) f->column[i].name, f->column[i].name, DBASE_COLUMN_NAME_SIZE); f->column[i].value = ptr; ptr += f->column[i].length; }
*lpf = f; */ return DBASE_ERR_SUCCESS;
}
/***************************************************************************/
SWORD FAR PASCAL dBaseFlushDirtyRecord(LPDBASEFILE f) { /*
LONG offset; UCHAR c; UDWORD currentRecord;
// Is there a dirty record?
if (f->recordDirty) {
// Yes. Write it back
f->recordDirty = FALSE; if (f->sortArray == NULL) currentRecord = f->currentRecord-1; else currentRecord = f->sortArray[f->currentRecord-1]; offset = f->headerSize + (currentRecord * f->recordSize); if (HFILE_ERROR == _llseek(f->hf, offset, 0)) { f->newRecord = FALSE; f->currentRecord = 0; return DBASE_ERR_CORRUPTFILE; } AnsiToOemBuff((LPCSTR) f->record, f->record, f->recordSize); if (f->recordSize != _lwrite(f->hf, (LPCSTR) f->record, f->recordSize)) { f->newRecord = FALSE; f->currentRecord = 0; return DBASE_ERR_WRITEERROR; }
// Was this a new record?
if (f->newRecord) {
// Yes. Write the end-of-data mark
f->newRecord = FALSE; c = DBASE_FILE_END; if (1 != _lwrite(f->hf, (LPCSTR) &c, 1)) { f->currentRecord = 0; return DBASE_ERR_WRITEERROR; } }
// Write back the header
f->headerDirty = TRUE; } */ return DBASE_ERR_SUCCESS;
} /***************************************************************************/
SWORD FAR PASCAL dBaseQuickSortKeyCompare(LPDBASEFILE f, UWORD icol, BOOL descending, UDWORD left, UDWORD right, BOOL FAR *result)
/* Is the key of the left greater than or equal the key of the right? */
{ /*
SWORD err; UWORD size; UCHAR szLeft[255]; UCHAR szRight[255]; SDOUBLE dblLeft; SDOUBLE dblRight; BOOL nullLeft; BOOL nullRight;
// Handle boundry conditions
if (left == LAST_RECORD) { *result = TRUE; return DBASE_ERR_SUCCESS; } if (right == FIRST_RECORD) { *result = TRUE; return DBASE_ERR_SUCCESS; } if (left == FIRST_RECORD) { *result = FALSE; return DBASE_ERR_SUCCESS; } if (right == LAST_RECORD) { *result = FALSE; return DBASE_ERR_SUCCESS; }
// Position to the right record
if (HFILE_ERROR == _llseek(f->hf, f->headerSize + (right * f->recordSize), 0)) return DBASE_ERR_CORRUPTFILE;
// Read the right record
size = _lread(f->hf, f->record, f->recordSize); if (size != f->recordSize) return DBASE_ERR_CORRUPTFILE; OemToAnsiBuff((LPCSTR) f->record, (LPSTR) f->record, f->recordSize); *(f->record) = DBASE_RECORD_NOT_DELETED;
// Get the right key
switch (f->column[icol-1].type) { case DBASE_CHAR: case DBASE_LOGICAL: case DBASE_DATE: case DBASE_MEMO: err = dBaseColumnCharVal(f, icol, 0, 255, szRight, &nullRight); break; case DBASE_NUMERIC: case DBASE_FLOAT: err = dBaseColumnNumVal(f, icol, &dblRight, &nullRight); break; } if (err != DBASE_ERR_SUCCESS) return err;
// If right is null, return TRUE
if (nullRight) { *result = TRUE; return DBASE_ERR_SUCCESS; }
// Position to the left record
if (HFILE_ERROR == _llseek(f->hf, f->headerSize + (left * f->recordSize), 0)) return DBASE_ERR_CORRUPTFILE;
// Read the left record
size = _lread(f->hf, f->record, f->recordSize); if (size != f->recordSize) return DBASE_ERR_CORRUPTFILE; OemToAnsiBuff((LPCSTR) f->record, (LPSTR) f->record, f->recordSize); *(f->record) = DBASE_RECORD_NOT_DELETED;
// Get the left key
switch (f->column[icol-1].type) { case DBASE_CHAR: case DBASE_LOGICAL: case DBASE_DATE: case DBASE_MEMO: err = dBaseColumnCharVal(f, icol, 0, 255, szLeft, &nullLeft); break; case DBASE_NUMERIC: case DBASE_FLOAT: err = dBaseColumnNumVal(f, icol, &dblLeft, &nullLeft); break; } if (err != DBASE_ERR_SUCCESS) return err;
// If left is null, return FALSE
if (nullRight) { *result = FALSE; return DBASE_ERR_SUCCESS; }
// Compare the keys
switch (f->column[icol-1].type) { case DBASE_CHAR: case DBASE_LOGICAL: case DBASE_DATE: case DBASE_MEMO: if (!descending) { if (s_lstrcmp(szLeft, szRight) >= 0) *result = TRUE; else *result = FALSE; } else { if (s_lstrcmp(szLeft, szRight) <= 0) *result = TRUE; else *result = FALSE; } break; case DBASE_NUMERIC: case DBASE_FLOAT: if (!descending) { if (dblLeft >= dblRight) *result = TRUE; else *result = FALSE; } else { if (dblLeft <= dblRight) *result = TRUE; else *result = FALSE; } break; } */ return DBASE_ERR_SUCCESS;
} /***************************************************************************/
SWORD FAR PASCAL dBaseQuickSort(LPDBASEFILE f, UWORD icol, BOOL descending, UDWORD FAR *sortArray, UDWORD left, UDWORD right) { /*
UDWORD i; UDWORD j; UDWORD temp; SWORD err; BOOL result;
// Q1:
if (right <= left) return DBASE_ERR_SUCCESS; // Q2:
i = left; j = right+1;
while (TRUE) {
// Q3:
while (TRUE) { i++; err = dBaseQuickSortKeyCompare(f, icol, descending, sortArray[i], sortArray[left], &result); if (err != DBASE_ERR_SUCCESS) return err; if (result) break; }
// Q4:
while (TRUE) { j--; err = dBaseQuickSortKeyCompare(f, icol, descending, sortArray[left], sortArray[j], &result); if (err != DBASE_ERR_SUCCESS) return err; if (result) break; }
// Q5:
if (j <= i) break;
// Q6:
temp = sortArray[j]; sortArray[j] = sortArray[i]; sortArray[i] = temp; }
// Q5:
temp = sortArray[left]; sortArray[left] = sortArray[j]; sortArray[j] = temp;
// Q7:
err = dBaseQuickSort(f, icol, descending, sortArray, left, j-1); if (err != DBASE_ERR_SUCCESS) return err;
// Q8:
err = dBaseQuickSort(f, icol, descending, sortArray, j+1, right); if (err != DBASE_ERR_SUCCESS) return err; */ return DBASE_ERR_SUCCESS;
} /***************************************************************************/ /***************************************************************************/
SWORD FAR PASCAL dBaseCreate(LPUSTR name) { /*
UCHAR FAR * ptr; DBASEFILE header; HFILE hf; int i; HANDLE h; UCHAR NEAR *fullname; UCHAR c; HANDLE ht; time_t *t; struct tm *ts;
// Get the filename
h = LocalAlloc(LMEM_MOVEABLE, DBASE_MAX_PATHNAME_SIZE+1); fullname = (UCHAR NEAR *) LocalLock(h); lstrcpy(fullname, name); ptr = fullname + lstrlen(fullname); while ((ptr != fullname) && (*ptr != '\\') && (*ptr != ':') && (*ptr != '.')) ptr--; if (*ptr != '.') lstrcat(fullname, ".dbf");
// Open the file
hf = _lcreat(fullname, 0); if (hf == HFILE_ERROR) { LocalUnlock(h); LocalFree(h); return DBASE_ERR_CREATEERROR; }
// Set up the header
header.flag = DBASE_3_FILE; ht = LocalAlloc(LMEM_MOVEABLE, sizeof(time_t)); t = (time_t NEAR *) LocalLock(ht); time(t); ts = localtime(t); LocalUnlock(ht); LocalFree(ht); header.year = ts->tm_year; header.month = ts->tm_mon + 1; header.day = ts->tm_mday; header.recordCount = 0; header.headerSize = DBASE_HEADER_LENGTH + 1; header.recordSize = 1; for (i=0; (i < 2); i++) header.reserved1[i] = 0; header.transaction = 0; header.encrypted = DBASE_NOT_ENCRYPTED; for (i=0; (i < 12); i++) header.reserved2[i] = 0; header.mdx = DBASE_MDX_FLAG_OFF; for (i=0; (i < 3); i++) header.reserved3[i] = 0;
// Write the header
if (DBASE_HEADER_LENGTH != _lwrite(hf, (LPSTR) &header, DBASE_HEADER_LENGTH)) { _lclose(hf); AnsiToOem(fullname, fullname); #ifdef WIN32
DeleteFile(fullname); #else
remove(fullname); #endif
LocalUnlock(h); LocalFree(h); return DBASE_ERR_WRITEERROR; }
// Write the end-of-columns mark
c = DBASE_END_OF_COLUMNS; if (1 != _lwrite(hf, &c, 1)) { _lclose(hf); AnsiToOem(fullname, fullname); #ifdef WIN32
DeleteFile(fullname); #else
remove(fullname); #endif
LocalUnlock(h); LocalFree(h); return DBASE_ERR_WRITEERROR; }
// Write the end-of-data mark
c = DBASE_FILE_END; if (1 != _lwrite(hf, &c, 1)) { _lclose(hf); AnsiToOem(fullname, fullname); #ifdef WIN32
DeleteFile(fullname); #else
remove(fullname); #endif
LocalUnlock(h); LocalFree(h); return DBASE_ERR_WRITEERROR; }
// Close the file
if (HFILE_ERROR == _lclose(hf)) { AnsiToOem(fullname, fullname); #ifdef WIN32
DeleteFile(fullname); #else
remove(fullname); #endif
LocalUnlock(h); LocalFree(h); return DBASE_ERR_CLOSEERROR; } LocalUnlock(h); LocalFree(h); */ return DBASE_ERR_SUCCESS;
}
/***************************************************************************/
SWORD FAR PASCAL dBaseAddColumn(LPUSTR name, LPUSTR colName, UCHAR type, UCHAR length, UCHAR scale) { /*
LPDBASEFILE f; LPSTR from; int i; LONG offset; UCHAR c; SWORD err;
// Check the column name
if (lstrlen(colName) > DBASE_COLUMN_NAME_SIZE) return DBASE_ERR_NOTSUPPORTED;
// Check the length and scale
switch (type) { case DBASE_CHAR: if ((length == 0) || (length > 254)) return DBASE_ERR_NOTSUPPORTED; scale = 0; break; case DBASE_NUMERIC: case DBASE_FLOAT: if ((length == 0) || (length > 19)) return DBASE_ERR_NOTSUPPORTED; if (length == 1) { if (scale != 0) return DBASE_ERR_NOTSUPPORTED; } else if (((UCHAR) (scale+2)) > length) return DBASE_ERR_NOTSUPPORTED; break; case DBASE_LOGICAL: length = 1; scale = 0; break; case DBASE_DATE: length = 8; scale = 0; break; case DBASE_MEMO: return DBASE_ERR_NOTSUPPORTED; default: return DBASE_ERR_NOTSUPPORTED; }
// Open the file
err = dBaseExtendedOpen(name, FALSE, 1, &f) ; if (err != DBASE_ERR_SUCCESS) return err;
if (f->recordCount != 0) { dBaseClose(f); return DBASE_ERR_NOTSUPPORTED; }
// Fill in the new entry
from = colName; for (i=0; (i < DBASE_COLUMN_NAME_SIZE); i++) { f->column[f->columnCount].name[i] = *from; if (*from != 0) from++; } f->column[f->columnCount].type = type; for (i=0; (i < 4); i++) f->column[f->columnCount].reserved1[i] = 0; f->column[f->columnCount].length = length; f->column[f->columnCount].scale = scale; for (i=0; (i < 2); i++) f->column[f->columnCount].reserved2[i] = 0; f->column[f->columnCount].workarea = 0; for (i=0; (i < 10); i++) f->column[f->columnCount].reserved3[i] = 0; f->column[f->columnCount].mdx = DBASE_MDX_FLAG_OFF; f->column[f->columnCount].value = NULL;
// Write the new column information
offset = DBASE_HEADER_LENGTH + (f->columnCount*DBASE_COLUMN_DESCR_LENGTH); if (HFILE_ERROR == _llseek(f->hf, offset, 0)) { dBaseClose(f); return DBASE_ERR_CORRUPTFILE; } AnsiToOemBuff(f->column[f->columnCount].name, f->column[f->columnCount].name, DBASE_COLUMN_NAME_SIZE); if (DBASE_COLUMN_DESCR_LENGTH != _lwrite(f->hf, (LPSTR) &(f->column[f->columnCount]), DBASE_COLUMN_DESCR_LENGTH)) { dBaseClose(f); return DBASE_ERR_WRITEERROR; }
// Adust header information
(f->columnCount)++; f->headerSize += DBASE_COLUMN_DESCR_LENGTH; f->recordSize += length; if (type == DBASE_FLOAT) f->flag = DBASE_4_FILE;
// Put in end-of-columns mark
c = DBASE_END_OF_COLUMNS; if (1 != _lwrite(f->hf, &c, 1)) { dBaseClose(f); return DBASE_ERR_WRITEERROR; }
// Put in end-of-data mark
c = DBASE_FILE_END; if (1 != _lwrite(f->hf, &c, 1)) { dBaseClose(f); return DBASE_ERR_WRITEERROR; }
// Close the file
f->headerDirty = TRUE; err = dBaseClose(f); if (err != DBASE_ERR_SUCCESS) return err; */ return DBASE_ERR_SUCCESS;
}
/***************************************************************************/
SWORD FAR PASCAL dBaseOpen(LPUSTR name, BOOL fReadOnly, LPDBASEFILE FAR *lpf) { return dBaseExtendedOpen(name, fReadOnly, 0, lpf); }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnCount(LPDBASEFILE f, UWORD FAR *count) { // *count = f->columnCount;
return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnName(LPDBASEFILE f, UWORD icol, LPUSTR name) { /*
int i;
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN;
for (i = 0; i < DBASE_COLUMN_NAME_SIZE; i++) name[i] = f->column[icol-1].name[i]; name[DBASE_COLUMN_NAME_SIZE] = '\0'; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnType(LPDBASEFILE f, UWORD icol, UCHAR FAR *type) { /*
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN;
*type = f->column[icol-1].type; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnLength(LPDBASEFILE f, UWORD icol, UCHAR FAR *len) { /*
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN;
*len = f->column[icol-1].length; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnScale(LPDBASEFILE f, UWORD icol, UCHAR FAR *scale) { /*
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN;
*scale = f->column[icol-1].scale; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseSort(LPDBASEFILE f, UWORD icol, BOOL descending) { /*
SWORD err; HANDLE h; UDWORD FAR *sortArray; UDWORD idx;
// Make sure column is really there
if ((icol > f->columnCount) || (icol < 0)) return DBASE_ERR_NOSUCHCOLUMN;
// Write back any pending writes
err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err;
// Remove sort order (if any)
if (f->sortArray != NULL) { GlobalUnlock(GlobalPtrHandle (f->sortArray)); GlobalFree(GlobalPtrHandle(f->sortArray)); f->sortArray = NULL; }
// Is there a new sort?
if (icol != 0) {
// Yes. Allocate space for new sort
h = GlobalAlloc (GMEM_MOVEABLE, (sizeof(UDWORD) * (f->recordCount + 2))); if (h == NULL || (sortArray = (UDWORD FAR *)GlobalLock (h)) == NULL) return DBASE_ERR_MEMALLOCFAIL;
// Fill in the sort array
sortArray[0] = FIRST_RECORD; for (idx = 1; idx < f->recordCount+1; idx++) sortArray[idx] = idx-1; sortArray[f->recordCount+1] = LAST_RECORD;
// Sort the records
f->currentRecord = 1; err = dBaseQuickSort(f, icol, descending, sortArray, 1, f->recordCount); if (err != DBASE_ERR_SUCCESS) { f->currentRecord = 0; GlobalUnlock(h); GlobalFree(h); return err; } f->currentRecord = 0;
// Move the items into place
for (idx = 0; idx < f->recordCount; idx++) sortArray[idx] = sortArray[idx+1]; sortArray[f->recordCount] = f->recordCount; f->sortArray = sortArray; }
// Position before record
f->currentRecord = 0; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseReadFirst(LPDBASEFILE f) { /*
LONG offset; SWORD err; UWORD size; UDWORD currentRecord;
// Write back any pending writes
err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err;
// Position to the first record
if (f->sortArray == NULL) currentRecord = 0; else currentRecord = f->sortArray[0]; offset = f->headerSize + (currentRecord * f->recordSize); if (HFILE_ERROR == _llseek(f->hf, offset, 0)) return DBASE_ERR_CORRUPTFILE;
// Read the record
size = _lread(f->hf, f->record, f->recordSize); if (size == 1) { if (*(f->record) == DBASE_FILE_END) return DBASE_ERR_NODATAFOUND; else return DBASE_ERR_CORRUPTFILE; } if (size != f->recordSize) return DBASE_ERR_CORRUPTFILE; f->currentRecord = 1;
// If this record is deleted, return next record
if (*(f->record) == DBASE_RECORD_DELETED) return dBaseReadNext(f);
// Return record
OemToAnsiBuff(f->record, f->record, f->recordSize); */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseReadNext(LPDBASEFILE f) { /*
LONG offset; SWORD err; UWORD size; UDWORD currentRecord;
// Write back any pending writes
err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err;
// Position to the next record
if (f->sortArray == NULL) currentRecord = f->currentRecord; else currentRecord = f->sortArray[f->currentRecord]; offset = f->headerSize + (currentRecord * f->recordSize); if (HFILE_ERROR == _llseek(f->hf, offset, 0)) return DBASE_ERR_CORRUPTFILE;
// Read the record
size = _lread(f->hf, f->record, f->recordSize); if (size == 1) { if (*(f->record) == DBASE_FILE_END) return DBASE_ERR_NODATAFOUND; else return DBASE_ERR_CORRUPTFILE; } if (size != f->recordSize) return DBASE_ERR_CORRUPTFILE; f->currentRecord++;
// If this record is deleted, return next record
if (*(f->record) == DBASE_RECORD_DELETED) return dBaseReadNext(f);
// Return record
OemToAnsiBuff(f->record, f->record, f->recordSize); */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnCharVal(LPDBASEFILE f, UWORD icol, UDWORD offset, SDWORD bufsize, UCHAR FAR *val, BOOL FAR *isNull) { /*
LPDBASECOL lpCol; UCHAR FAR *fromPtr; UCHAR FAR *toPtr; UCHAR i; UWORD year; UWORD month; UWORD day; */ SWORD err; /*
// Make sure data is really there
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN; if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
// Get the data
lpCol = &(f->column[icol-1]); fromPtr = lpCol->value; */ err = DBASE_ERR_SUCCESS; /*
switch (lpCol->type) { case DBASE_CHAR: toPtr = val; *isNull = TRUE; if (bufsize <= ((SDWORD) lpCol->length)) { err = DBASE_ERR_TRUNCATION; } else { bufsize = lpCol->length; } for (i=0; i < (UCHAR) bufsize; i++) { if (*fromPtr != ' ') *isNull = FALSE; if (toPtr != NULL) { *toPtr = *fromPtr; toPtr++; } fromPtr++; } if (toPtr != NULL) *toPtr = '\0'; break; case DBASE_FLOAT: case DBASE_NUMERIC: i = lpCol->length; while ((*fromPtr == ' ') && (i > 0)) { fromPtr++; i--; } toPtr = val; *isNull = TRUE; for (;i > 0; i--) { if (toPtr != NULL) { *toPtr = *fromPtr; toPtr++; } fromPtr++; *isNull = FALSE; } if (toPtr != NULL) *toPtr = '\0'; break; case DBASE_DATE: if (*fromPtr == ' ') *isNull = TRUE; else { *isNull = FALSE; year = ((fromPtr[0] & 0x0F) * 1000) + ((fromPtr[1] & 0x0F) * 100) + ((fromPtr[2] & 0x0F) * 10) + (fromPtr[3] & 0x0F); month = ((fromPtr[4] & 0x0F) * 10) + (fromPtr[5] & 0x0F); day = ((fromPtr[6] & 0x0F) * 10) + (fromPtr[7] & 0x0F); if (val != NULL) wsprintf(val, "%04d-%02d-%02d", year, month, day); } break; case DBASE_LOGICAL: switch (*fromPtr) { case 'Y': case 'y': case 'T': case 't': case '1': if (val != NULL) lstrcpy(val, "1"); *isNull = FALSE; break; case 'N': case 'n': case 'F': case 'f': case '0': if (val != NULL) lstrcpy(val, "0"); *isNull = FALSE; break; case '?': case ' ': *isNull = TRUE; break; } break; case DBASE_MEMO: *isNull = TRUE; break; } if ((*isNull) && (val != NULL)) lstrcpy(val, ""); */ return err; }
/***************************************************************************/
SWORD FAR PASCAL dBaseColumnNumVal(LPDBASEFILE f, UWORD icol, SDOUBLE FAR *val, BOOL FAR *isNull) { /*
LPDBASECOL lpCol; UCHAR i; double d; BOOL neg; UCHAR FAR *fromPtr; BOOL foundDecimalPoint; short scale; BOOL negexp; short exp;
// Make sure data is really there
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN; if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
// Get the data
lpCol = &(f->column[icol-1]); fromPtr = lpCol->value; switch (lpCol->type) { case DBASE_CHAR: case DBASE_FLOAT: case DBASE_NUMERIC: *isNull = TRUE; for (i=0; i < lpCol->length; i++) { if (*fromPtr != ' ') break; fromPtr++; }
neg = FALSE; if (i < lpCol->length) { if (*fromPtr == '-') { neg = TRUE; fromPtr++; i++; } }
d = 0.0; scale = 0; foundDecimalPoint = FALSE; for (;i < lpCol->length; i++) { if (!foundDecimalPoint && (*fromPtr == '.')) foundDecimalPoint = TRUE; else { if ((*fromPtr == 'E') || (*fromPtr == 'e')) { fromPtr++; i++; if (i < lpCol->length) { if (*fromPtr == '-') { negexp = TRUE; fromPtr++; i++; } else if (*fromPtr == '+') { negexp = FALSE; fromPtr++; i++; } else negexp = FALSE; } else negexp = FALSE; exp = 0; for (;i < lpCol->length; i++) { if ((*fromPtr < '0') || (*fromPtr > '9')) return DBASE_ERR_CONVERSIONERROR; exp = (exp * 10) + (*fromPtr - '0'); fromPtr++; } if (negexp) scale = scale + exp; else scale = scale - exp; break; } if ((*fromPtr < '0') || (*fromPtr > '9')) return DBASE_ERR_CONVERSIONERROR; d = (d * 10) + (*fromPtr - '0'); *isNull = FALSE; if (foundDecimalPoint) scale++; } fromPtr++; }
for (; (0 < scale); scale--) d /= 10; for (; (0 > scale); scale++) d *= 10;
if (val != NULL) { if (neg) *val = -d; else *val = d; } break; case DBASE_DATE: return DBASE_ERR_CONVERSIONERROR; case DBASE_LOGICAL: switch (*fromPtr) { case 'Y': case 'y': case 'T': case 't': case '1': if (val != NULL) *val = 1.0; *isNull = FALSE; break; case 'N': case 'n': case 'F': case 'f': case '0': if (val != NULL) *val = 0.0; *isNull = FALSE; break; case '?': case ' ': *isNull = TRUE; break; } break; case DBASE_MEMO: *isNull = TRUE; break; } if ((val != NULL) && (*isNull)) *val = 0.0; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseAddRecord(LPDBASEFILE f) { /*
UWORD i; UCHAR FAR * ptr; SWORD err;
// Write dirty record
err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err;
// Remove sort order (if any)
if (f->sortArray != NULL) { GlobalUnlock(GlobalPtrHandle(f->sortArray)); GlobalFree(GlobalPtrHandle(f->sortArray)); f->sortArray = NULL; }
// Create null record
ptr = f->record; for (i=0; i < f->recordSize; i++) { *ptr = ' '; ptr++; } f->recordDirty = TRUE; f->newRecord = TRUE;
// Increment record count
f->recordCount++; f->headerDirty = TRUE;
// Reset current record
f->currentRecord = f->recordCount; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseSetColumnCharVal(LPDBASEFILE f, UWORD icol, UCHAR FAR *val, SDWORD size) { /*
LPDBASECOL lpCol; UCHAR FAR *fromPtr; UCHAR FAR *toPtr; UCHAR FAR *decimalLocation; UCHAR FAR *valStart; UCHAR FAR *valEnd; UCHAR FAR *ptr; UCHAR length; UCHAR i; SWORD extraZeros; BOOL negNeeded; BOOL foundExp; SWORD err;
// Make sure data is really there
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN; if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
// Set value
lpCol = &(f->column[icol-1]); toPtr = lpCol->value; err = DBASE_ERR_SUCCESS; switch (lpCol->type) { case DBASE_CHAR: fromPtr = val; for (i=0; i < lpCol->length; i++) { if (((SDWORD) i) == size) break; *toPtr = *fromPtr; toPtr++; fromPtr++; } for (; i < lpCol->length; i++) { *toPtr = ' '; toPtr++; } if (((SDWORD) lpCol->length) < size) err = DBASE_ERR_TRUNCATION; break; case DBASE_FLOAT: case DBASE_NUMERIC:
// If a zero length string is specifed, point to a zero
if ((lpCol->scale == 0) && (size == 0)) { val = "0"; size = 1; } // Point at start of value
length = lpCol->length - 1; valStart = val; if (*valStart == '-') { valStart++; }
// Make sure all characters are legal and find decimal point
foundExp = FALSE; decimalLocation = NULL; fromPtr = valStart; i = 0; while (((SDWORD) i) < size) { if (*fromPtr == '\0') break; else if (*fromPtr == '.') { if ((decimalLocation != NULL) || (foundExp)) return DBASE_ERR_CONVERSIONERROR; decimalLocation = fromPtr; } else if ((*fromPtr == 'E') || (*fromPtr == 'e')) { if (foundExp) return DBASE_ERR_CONVERSIONERROR; foundExp = TRUE; if ((*fromPtr == '-') || (*fromPtr == '+')) { fromPtr++; i++; } } else if (!(IsCharAlphaNumeric(*fromPtr)) || IsCharAlpha(*fromPtr)) return DBASE_ERR_CONVERSIONERROR; fromPtr++; i++; }
// Scientific notation?
if (foundExp) {
// Yes. Error if not enough room for value
if (size > (SDWORD) lpCol->length) return DBASE_ERR_CONVERSIONERROR;
// Copy the value
for (i=0; (SWORD) i < (SWORD) lpCol->length - lstrlen(val); i++) { *toPtr = ' '; toPtr++; } fromPtr = val; while (*fromPtr) { *toPtr = *fromPtr; toPtr++; fromPtr++; } break; }
// Find end of value
valEnd = fromPtr-1; if (decimalLocation == valEnd) { valEnd--; decimalLocation = NULL; }
// Truncate extra characters at end
if (decimalLocation != NULL) { if (lpCol->scale == 0) { valEnd = decimalLocation-1; decimalLocation = NULL; } else { if ((SWORD) lpCol->scale < (valEnd - decimalLocation)) { valEnd = decimalLocation + lpCol->scale; } } }
// Figure out how many extra zeros need to be added at end
if (lpCol->scale == 0) extraZeros = 0; else if (decimalLocation == NULL) extraZeros = lpCol->scale + 1; else extraZeros = lpCol->scale - (valEnd - decimalLocation);
// Shave off extra characters in front
while ((SWORD) length < (valEnd - valStart) + 1 + extraZeros) valStart++;
// Put in leading spaces
for (i=0; (SWORD) i < (length - (valEnd - valStart + 1) - extraZeros); i++) { *toPtr = ' '; toPtr++; }
// Put in sign if needed
negNeeded = FALSE; if (*val == '-') { for (ptr = valStart; ptr <= valEnd; ptr++) { if ((*ptr != '0') && (*ptr != '.')) { negNeeded = TRUE; break; } } } if (negNeeded) *toPtr = '-'; else *toPtr = ' '; toPtr++;
// Put in value
while (valStart <= valEnd) { *toPtr = *valStart; toPtr++; valStart++; }
// Put in required trailing zeros
if (extraZeros == lpCol->scale + 1) { *toPtr = '.'; toPtr++; extraZeros--; } while (extraZeros > 0) { *toPtr = '0'; toPtr++; extraZeros--; } break;
case DBASE_DATE: // Make sure value is legal
if (size != 10) return DBASE_ERR_CONVERSIONERROR; for (i=0; i < 10; i++) { switch (i) { case 0: case 1: case 2: case 3: case 6: case 9: if (!(IsCharAlphaNumeric(val[i])) || IsCharAlpha(val[i])) return DBASE_ERR_CONVERSIONERROR; break; case 4: case 7: if (val[i] != '-') return DBASE_ERR_CONVERSIONERROR; break; case 5: if ((val[i] < '0') || (val[i] > '1')) return DBASE_ERR_CONVERSIONERROR; break; case 8: if ((val[i] < '0') && (val[i] > '3')) return DBASE_ERR_CONVERSIONERROR; if ((val[i] == '3') && (val[i+1] > '1')) return DBASE_ERR_CONVERSIONERROR; break; } }
// Copy the value
for (i=0; i < 4; i++) { *toPtr = val[i]; toPtr++; } for (i=5; i < 7; i++) { *toPtr = val[i]; toPtr++; } for (i=8; i < 10; i++) { *toPtr = val[i]; toPtr++; } break; case DBASE_LOGICAL: if (size != 1) return DBASE_ERR_CONVERSIONERROR; switch (*val) { case 'Y': case 'y': case 'T': case 't': case '1': *toPtr = 'Y'; break; case 'N': case 'n': case 'F': case 'f': case '0': *toPtr = 'N'; break; case '?': case ' ': *toPtr = '?'; break; default: return DBASE_ERR_CONVERSIONERROR; } break; case DBASE_MEMO: break; } f->recordDirty = TRUE; */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseSetColumnNull(LPDBASEFILE f, UWORD icol) { /*
UCHAR i; LPDBASECOL lpCol;
// Make sure data is really there
if ((icol > f->columnCount) || (icol <= 0)) return DBASE_ERR_NOSUCHCOLUMN; if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
// Set value
lpCol = &(f->column[icol-1]); if (lpCol->type == DBASE_MEMO) return DBASE_ERR_NOTSUPPORTED; for (i=0; (i < f->column[icol-1].length); i++) f->column[icol-1].value[i] = ' '; f->recordDirty = TRUE; */ return DBASE_ERR_SUCCESS; } /***************************************************************************/
SWORD FAR PASCAL dBaseDeleteRecord(LPDBASEFILE f) { /*
if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
if (f->newRecord) { f->recordDirty = FALSE; f->newRecord = FALSE; f->recordCount--; f->headerDirty = TRUE; f->currentRecord = 0; } else { *(f->record) = DBASE_RECORD_DELETED; f->recordDirty = TRUE; } */ return DBASE_ERR_SUCCESS; } /***************************************************************************/ SWORD FAR PASCAL dBaseGetBookmark(LPDBASEFILE f, UDWORD far *b) { /*
// Make sure data is really there
if (f->currentRecord == 0) return DBASE_ERR_NODATAFOUND; if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
if (f->sortArray == NULL) *b = f->currentRecord-1; else *b = f->sortArray[f->currentRecord-1]; */ return DBASE_ERR_SUCCESS; } /***************************************************************************/ SWORD FAR PASCAL dBasePosition(LPDBASEFILE f, UDWORD b) { /*
LONG offset; SWORD err; UWORD size;
// Write back any pending writes
err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err;
// Position to the specified record
offset = f->headerSize + (b * f->recordSize); if (HFILE_ERROR == _llseek(f->hf, offset, 0)) return DBASE_ERR_CORRUPTFILE;
// Read the record
size = _lread(f->hf, f->record, f->recordSize); if (size == 1) { if (*(f->record) == DBASE_FILE_END) return DBASE_ERR_NODATAFOUND; else return DBASE_ERR_CORRUPTFILE; } if (size != f->recordSize) return DBASE_ERR_CORRUPTFILE; f->currentRecord = b+1;
// If this record is deleted, return error
if (*(f->record) == DBASE_RECORD_DELETED) return DBASE_ERR_NODATAFOUND;
// Return record
OemToAnsiBuff(f->record, f->record, f->recordSize); */ return DBASE_ERR_SUCCESS; } /***************************************************************************/
SWORD FAR PASCAL dBaseClose(LPDBASEFILE f) { /*
SWORD err; HANDLE ht; time_t *t; struct tm *ts;
if (f->headerDirty) { ht = LocalAlloc(LMEM_MOVEABLE, sizeof(time_t)); t = (time_t NEAR *) LocalLock(ht); time(t); ts = localtime(t); LocalUnlock(ht); LocalFree(ht); f->year = ts->tm_year; f->month = ts->tm_mon + 1; f->day = ts->tm_mday; if (HFILE_ERROR == _llseek(f->hf, 0, 0)) return DBASE_ERR_CORRUPTFILE; if (DBASE_HEADER_LENGTH != _lwrite(f->hf, (LPSTR) f, DBASE_HEADER_LENGTH)) return DBASE_ERR_WRITEERROR; } err = dBaseFlushDirtyRecord(f); if (err != DBASE_ERR_SUCCESS) return err; if (HFILE_ERROR == _lclose(f->hf)) return DBASE_ERR_CLOSEERROR; if (f->sortArray != NULL) { GlobalUnlock(GlobalPtrHandle(f->sortArray)); GlobalFree(GlobalPtrHandle(f->sortArray)); } GlobalUnlock(GlobalPtrHandle(f)); GlobalFree(GlobalPtrHandle(f)); */ return DBASE_ERR_SUCCESS; }
/***************************************************************************/
SWORD FAR PASCAL dBaseDestroy(LPUSTR name) { /*
UCHAR FAR * ptr; HANDLE h; UCHAR NEAR *fullname;
// Get the filename
h = LocalAlloc(LMEM_MOVEABLE, DBASE_MAX_PATHNAME_SIZE+1); fullname = (UCHAR NEAR *) LocalLock(h); lstrcpy(fullname, name); ptr = fullname + lstrlen(fullname); while ((ptr != fullname) && (*ptr != '\\') && (*ptr != ':') && (*ptr != '.')) ptr--; if (*ptr != '.') lstrcat(fullname, ".dbf");
AnsiToOem(fullname, fullname); #ifdef WIN32
DeleteFile(fullname); #else
remove(fullname); #endif
LocalUnlock(h); LocalFree(h); */ return DBASE_ERR_SUCCESS; } /***************************************************************************/
|