📄 emfdb.c
字号:
int tid, colIndex, *pRow;
dbTable_t *pTable;
a_assert(table);
a_assert(column);
/*
* Make sure that this table exists
*/
tid = dbGetTableId(0, table);
a_assert(tid >= 0);
if (tid < 0) {
return DB_ERR_TABLE_NOT_FOUND;
}
pTable = dbListTables[tid];
if (pTable) {
/*
* Make sure that the column exists
*/
colIndex = GetColumnIndex(tid, column);
a_assert(colIndex >= 0);
if (colIndex >= 0) {
/*
* Make sure that the row exists
*/
a_assert((row >= 0) && (row < pTable->nRows));
if ((row >= 0) && (row < pTable->nRows)) {
pRow = pTable->rows[row];
if (pRow) {
pRow[colIndex] = iData;
return 0;
}
return DB_ERR_ROW_DELETED;
}
return DB_ERR_ROW_NOT_FOUND;
}
return DB_ERR_COL_NOT_FOUND;
}
return DB_ERR_TABLE_DELETED;
}
/******************************************************************************/
/*
* The dbWriteStr function writes a string value into a table at a given row
* and column. The existence of the row and column is verified before the
* write. The column is also checked to confirm it is a string field.
* 0 is returned on succes, -1 is returned on error.
*/
int dbWriteStr(int did, char_t *table, char_t *column, int row, char_t *s)
{
int tid, colIndex;
int *pRow;
char_t *ptr;
dbTable_t *pTable;
a_assert(table);
a_assert(column);
tid = dbGetTableId(0, table);
a_assert(tid >= 0);
if (tid < 0) {
return DB_ERR_TABLE_NOT_FOUND;
}
/*
* Make sure that this table exists
*/
pTable = dbListTables[tid];
a_assert(pTable);
if (!pTable) {
return DB_ERR_TABLE_DELETED;
}
/*
* Make sure that this column exists
*/
colIndex = GetColumnIndex(tid, column);
if (colIndex < 0) {
return DB_ERR_COL_NOT_FOUND;
}
/*
* Make sure that this column is a string column
*/
if (pTable->columnTypes[colIndex] != T_STRING) {
return DB_ERR_BAD_FORMAT;
}
/*
* Make sure that the row exists
*/
a_assert((row >= 0) && (row < pTable->nRows));
if ((row >= 0) && (row < pTable->nRows)) {
pRow = pTable->rows[row];
} else {
return DB_ERR_ROW_NOT_FOUND;
}
if (!pRow) {
return DB_ERR_ROW_DELETED;
}
/*
* If the column already has a value, be sure to delete it to prevent
* memory leaks.
*/
if (pRow[colIndex]) {
bfree(B_L, (char_t *) pRow[colIndex]);
}
/*
* Make sure we make a copy of the string to write into the column.
* This allocated string will be deleted when the row is deleted.
*/
ptr = bstrdup(B_L, s);
pRow[colIndex] = (int)ptr;
return 0;
}
/******************************************************************************/
/*
* Print a key-value pair to a file
*/
static int dbWriteKeyValue(int fd, char_t *key, char_t *value)
{
int rc;
int len;
char_t *pLineOut;
a_assert(key && *key);
a_assert(value);
fmtAlloc(&pLineOut, BUF_MAX, T("%s=%s\n"), key, value);
if (pLineOut) {
len = gstrlen(pLineOut);
#ifdef CE
rc = writeUniToAsc(fd, pLineOut, len);
#else
rc = gwrite(fd, pLineOut, len);
#endif
bfree(B_L, pLineOut);
} else {
rc = -1;
}
return rc;
}
/******************************************************************************/
/*
* Persist a database to a file
*/
int dbSave(int did, char_t *filename, int flags)
{
int row, column, nColumns, nRows, fd, rc;
int *colTypes, *pRow, nRet, tid;
char_t *path, *tmpFile, *tmpNum;
char_t **colNames;
dbTable_t *pTable;
trace(5, T("DB: About to save database to file\n"));
a_assert(dbMaxTables > 0);
/*
* First write to a temporary file, then switch around later.
*/
fmtAlloc(&tmpFile, FNAMESIZE, T("%s/data.tmp"), basicGetProductDir());
if ((fd = gopen(tmpFile,
O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) {
trace(1, T("WARNING: Failed to open file %s\n"), tmpFile);
bfree(B_L, tmpFile);
return -1;
}
nRet = 0;
for (tid = 0; (tid < dbMaxTables) && (nRet != -1); tid++) {
pTable = dbListTables[tid];
if (pTable) {
/*
* Print the TABLE=tableName directive to the file
*/
rc = dbWriteKeyValue(fd, KEYWORD_TABLE, pTable->name);
nColumns = pTable->nColumns;
nRows = pTable->nRows;
for (row = 0; (row < nRows) && (nRet == 0); row++) {
pRow = pTable->rows[row];
/*
* if row is NULL, the row has been deleted, so don't
* write it out.
*/
if ((pRow == NULL) || (pRow[0] == '\0') ||
(*(char_t *)(pRow[0]) == '\0')) {
continue;
}
/*
* Print the ROW=rowNumber directive to the file
*/
fmtAlloc(&tmpNum, 20, T("%d"), row);
rc = dbWriteKeyValue(fd, KEYWORD_ROW, tmpNum);
bfreeSafe(B_L, tmpNum);
colNames = pTable->columnNames;
colTypes = pTable->columnTypes;
/*
* Print the key-value pairs (COLUMN=value) for data cells
*/
for (column = 0; (column < nColumns) && (rc >= 0);
column++, colNames++, colTypes++) {
if (*colTypes == T_STRING) {
rc = dbWriteKeyValue(fd, *colNames,
(char_t *)(pRow[column]));
} else {
fmtAlloc(&tmpNum, 20, T("%d"), pRow[column]);
rc = dbWriteKeyValue(fd, *colNames, tmpNum);
bfreeSafe(B_L, tmpNum);
}
}
if (rc < 0) {
trace(1, T("WARNING: Failed to write to file %s\n"),
tmpFile);
nRet = -1;
}
}
}
}
gclose(fd);
/*
* Replace the existing file with the temporary file, if no errors
*/
if (nRet == 0) {
fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);
gunlink(path);
if (grename(tmpFile, path) != 0) {
trace(1, T("WARNING: Failed to rename %s to %s\n"), tmpFile, path);
nRet = -1;
}
bfree(B_L, path);
}
bfree(B_L, tmpFile);
return nRet;
}
/******************************************************************************/
/*
* Crack a keyword=value string into keyword and value. We can change buf.
*/
static int crack(char_t *buf, char_t **key, char_t **val)
{
char_t *ptr;
if ((ptr = gstrrchr(buf, '\n')) != NULL ||
(ptr = gstrrchr(buf, '\r')) != NULL) {
*ptr = '\0';
}
/*
* Find the = sign. It must exist.
*/
if ((ptr = gstrstr(buf, T("="))) == NULL) {
return -1;
}
*ptr++ = '\0';
*key = trim(buf);
*val = trim(ptr);
return 0;
}
/******************************************************************************/
/*
* Parse the file. These files consist of key-value pairs, separated by the
* "=" sign. Parsing of tables starts with the "TABLE=value" pair, and rows
* are parsed starting with the "ROW=value" pair.
*/
int dbLoad(int did, char_t *filename, int flags)
{
gstat_t sbuf;
char_t *buf, *keyword, *value, *path, *ptr;
char_t *tablename;
int fd, tid, row;
dbTable_t *pTable;
a_assert(did >= 0);
fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);
trace(4, T("DB: About to read data file <%s>\n"), path);
if (gstat(path, &sbuf) < 0) {
trace(3, T("DB: Failed to stat persistent data file.\n"));
bfree(B_L, path);
return -1;
}
fd = gopen(path, O_RDONLY | O_BINARY, 0666);
bfree(B_L, path);
if (fd < 0) {
trace(3, T("DB: No persistent data file present.\n"));
return -1;
}
if (sbuf.st_size <= 0) {
trace(3, T("DB: Persistent data file is empty.\n"));
gclose(fd);
return -1;
}
/*
* Read entire file into temporary buffer
*/
buf = balloc(B_L, sbuf.st_size + 1);
#ifdef CE
if (readAscToUni(fd, &buf, sbuf.st_size) != (int)sbuf.st_size) {
#else
if (gread(fd, buf, sbuf.st_size) != (int)sbuf.st_size) {
#endif
trace(3, T("DB: Persistent data read failed.\n"));
bfree(B_L, buf);
gclose(fd);
return -1;
}
gclose(fd);
*(buf + sbuf.st_size) = '\0';
row = -1;
tid = -1;
pTable = NULL;
ptr = gstrtok(buf, T("\n"));
tablename = NULL;
do {
if (crack(ptr, &keyword, &value) < 0) {
trace(5, T("DB: Failed to crack line %s\n"), ptr);
continue;
}
a_assert(keyword && *keyword);
if (gstrcmp(keyword, KEYWORD_TABLE) == 0) {
/*
* Table name found, check to see if it's registered
*/
if (tablename) {
bfree(B_L, tablename);
}
tablename = bstrdup(B_L, value);
tid = dbGetTableId(did, tablename);
if (tid >= 0) {
pTable = dbListTables[tid];
} else {
pTable = NULL;
}
} else if (gstrcmp(keyword, KEYWORD_ROW) == 0) {
/*
* Row/Record indicator found, add a new row to table
*/
if (tid >= 0) {
int nRows = dbGetTableNrow(did, tablename);
if (dbSetTableNrow(did, tablename, nRows + 1) == 0) {
row = nRows;
}
}
} else if (row != -1) {
/*
* some other data found, assume it's a COLUMN=value
*/
int nColumn = GetColumnIndex(tid, keyword);
if ((nColumn >= 0) && (pTable != NULL)) {
int nColumnType = pTable->columnTypes[nColumn];
if (nColumnType == T_STRING) {
dbWriteStr(did, tablename, keyword, row, value);
} else {
dbWriteInt(did, tablename, keyword, row, gstrtoi(value));
}
}
}
} while ((ptr = gstrtok(NULL, T("\n"))) != NULL);
if (tablename) {
bfree(B_L, tablename);
}
bfree(B_L, buf);
return 0;
}
/******************************************************************************/
/*
* Return a table id given the table name
*/
int dbGetTableId(int did, char_t *tablename)
{
int tid;
dbTable_t *pTable;
a_assert(tablename);
for (tid = 0; (tid < dbMaxTables); tid++) {
if ((pTable = dbListTables[tid]) != NULL) {
if (gstrcmp(tablename, pTable->name) == 0) {
return tid;
}
}
}
return -1;
}
/******************************************************************************/
/*
* Return a pointer to the table name, given its ID
*/
char_t *dbGetTableName(int did, int tid)
{
if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
return (dbListTables[tid])->name;
}
return NULL;
}
/******************************************************************************/
/*
* Trim leading white space.
*/
static char_t *trim(char_t *str)
{
while (isspace((int)*str)) {
str++;
}
return str;
}
/******************************************************************************/
/*
* Return a column index given the column name
*/
static int GetColumnIndex(int tid, char_t *colName)
{
int column;
dbTable_t *pTable;
a_assert(colName);
if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
pTable = dbListTables[tid];
for (column = 0; (column < pTable->nColumns); column++) {
if (gstrcmp(colName, pTable->columnNames[column]) == 0)
return column;
}
}
return -1;
}
/******************************************************************************/
/*
* Set the prefix-directory
*/
void basicSetProductDir(char_t *proddir)
{
int len;
if (basicProdDir != NULL) {
bfree(B_L, basicProdDir);
}
basicProdDir = bstrdup(B_L, proddir);
/*
* Make sure that prefix-directory doesn't end with a '/'
*/
len = gstrlen(basicProdDir);
if ((len > 0) && *(basicProdDir + len - 1) == '/') {
*(basicProdDir+len-1) = '\0';
}
}
/******************************************************************************/
/*
* Return the prefix-directory
*/
char_t *basicGetProductDir()
{
if (basicProdDir) {
return basicProdDir;
} else {
return basicDefaultDir;
}
}
/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -