Disabled
Join Date: Dec 2001
Posts: 2,230
|
Just to show off, how trivial it's to write database modules for the new interface, I decided to publish source of current file database module (still work in progress = incomplete notepad draft) But it gives you idea, how much (or should I say little) work it's to write eg. SQL module.
Code:
LPWSTR *TokenizeCommaSeperatedString(LPWSTR wszInput, PULONG pStringCount)
{
PWCHAR pFrom, pTo, pBegin;
WCHAR wCurrent;
LPVOID lpMemory;
BOOL bBackSlash = FALSE;
ULONG lResultSize = 16;
ULONG lResultCount = 0;
LPWSTR *wszResult = 0;
/* tokenize comma seperated string */
wszResult = (LPWSTR *)Allocate("Tokenized string", sizeof(LPWSTR) * lResultSize);
if (! wszResult) {
/* out of memory */
return 0;
}
for (pFrom = pBegin = pTo = wszInput;;++pFrom) {
switch ((wCurrent = pFrom[0])) {
case L',':
if (bBackSlash) {
/* escaped comma */
break;
}
case L'\0':
if (bBackSlash) {
/* escaped nul.. decode failure */
Free(wszResult);
return 0;
}
if (lResultCount == lResultSize) {
lpMemory = ReAllocate(wszResult, 0, sizeof(LPWSTR) * (lResultSize + 16));
if (! lpMemory) {
/* out of memory */
Free(wszResult);
return 0;
}
lResultSize += 16;
wszResult = (LPWSTR *)lpMemory;
}
wszResult[lResultCount++] = pBegin;
if (wCurrent == L'\0') {
/* nul char */
pTo[0] = L'\0';
return wszResult;
}
pTo[0] = L'\0';
pTo = &pFrom[1];
pBegin = pTo;
continue;
case L'\\':
/* escape character */
if (bBackSlash) {
/* escaped escape character */
break;
}
bBackSlash = TRUE;
continue;
}
bBackSlash = FALSE;
if (pTo != pFrom) {
pTo++[0] = wCurrent;
continue;
}
pTo++;
}
}
LONG EscapeStringCommas(LPWSTR wszInput, LPWSTR wszOutput, ULONG lOutputSize)
{
WCHAR wCurrent;
PWCHAR pFrom, pTo;
LPWSTR wszResult;
/* escape string commas */
for (pFrom = wszInput, pTo = wszOutput;;pFrom++,pTo++) {
switch ((wCurrent = pFrom[0])) {
case L'\0':
return pTo - wszOutput;
case L'\\':
/* escape character */
if (lOutputSize < 2) {
/* out of buffer space */
break;
}
pTo++[0] = L'\\';
pTo++[0] = L'\\';
lOutputSize -= 2;
continue;
case L',':
/* comma */
if (lOutputSize < 2) {
/* out of buffer space */
break;
}
pTo++[0] = L'\\';
pTo++[0] = L',';
lOutputSize -= 2;
continue;
default:
if (! lOutputSize) {
/* out of buffer space */
break;
}
pTo++[0] = wCurrent;
lOutputSize--;
continue;
}
break;
}
return -1;
}
BOOL LockCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
/* lock and synchronize collection - does nothing for now */
return TRUE;
}
BOOL CommitCollectionChanges(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
LPDATABASE_ROW lpRow;
LPDATABASE_VALUE lpValue;
WCHAR wColumnName[16384], wColumnValue[16384];
LONG lColumnNameLength = 0;
LONG lColumnValueLength = 0;
LONG lResult;
DWORD dwBytesWritten;
ULONG lRowID, lRowIndex, lColumnID;
BOOL bError = FALSE;
BOOL bReturn = FALSE;
/* commit collection changes and release locks - no locks for now */
wColumnName[0] = L' ';
wColumnName[1] = L'{';
wColumnValue[0] = L'{';
hFile = CreateFileW(GetDatabaseCollectionName(lpCollection[0]),
GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
/* iterate all row ids */
for (lRowID = 0;lRowID < GetDatabaseRowIDCount(lpDatabase) && ! bError;lRowID++) {
/* iterate all rows */
for (lRowIndex = 0;lRowIndex < GetCollectionRowCount(lpCollection[0], lRowID);lRowIndex++) {
/* iterate all columns */
lpRow = GetCollectionRow(lpCollection[0], lRowID, lRowIndex);
if (! lpRow) {
continue;
}
lColumnValueLength = 1;
lColumnNameLength = _snwprintf(wColumnName,
sizeof(wColumnName) / sizeof(WCHAR) - 1, L"%s {", GetRowName(lpRow));
if (lColumnNameLength > 0) {
for (lColumnID = 0;lColumnID < GetRowColumnCount(lpRow);lColumnID++) {
lpValue = GetRowColumnValue(lpRow, lColumnID);
if (! lpValue) {
continue;
}
lResult = EscapeStringCommas(GetRowColumnName(lpRow, lColumnID),
&wColumnName[lColumnNameLength], sizeof(wColumnName) / sizeof(WCHAR) - lColumnNameLength - 2);
if (lResult <= 0) {
/* failure */
lColumnNameLength = INFINITE;
break;
}
lColumnNameLength += lResult;
wColumnName[lColumnNameLength++] = L',';
lResult = EscapeStringCommas(GetValueWString(lpValue),
&wColumnValue[lColumnValueLength], sizeof(wColumnValue) / sizeof(WCHAR) - lColumnValueLength - 3);
if (lResult < 0) {
/* failure */
lColumnValueLength = INFINITE;
break;
}
lColumnValueLength += lResult;
wColumnName[lColumnValueLength++] = L',';
}
if (lColumnValueLength != INFINITE && lColumnNameLength != INFINITE) {
/* prepend buffers */
wColumnName[lColumnNameLength - 1] = L'}';
wColumnName[lColumnNameLength++] = L' ';
wColumnValue[lColumnValueLength - 1] = L'}';
wColumnValue[lColumnValueLength++] = L'\r';
wColumnValue[lColumnValueLength++] = L'\n';
/* write to file */
if (WriteFile(hFile, wColumnName, lColumnNameLength * sizeof(WCHAR), &dwBytesWritten, 0)
&& WriteFile(hFile, wColumnValue, lColumnValueLength * sizeof(WCHAR), &dwBytesWritten, 0)) {
/* success */
continue;
}
}
} else {
/* out of buffer space */
lColumnNameLength = INFINITE;
}
bError = TRUE;
break;
}
}
CloseHandle(hFile);
if (! bError) {
bReturn = TRUE;
}
}
return bReturn;
}
BOOL CancelCollectionChanges(LPDATABASE lpDatabase, LPDATABASE_COLLECTION *lpCollection)
{
/* cancel collection changes and release locks - does nothing for now */
return TRUE;
}
BOOL QueryCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION lpCollection)
{
LPDATABASE_VALUE lpValue;
HANDLE hFile;
LPWSTR *wszColumnName, *wszColumnValue;
PWCHAR pLine, pBuffer, pEnd, pCurrent, pOpeningBrace[2], pClosingBrace, pWordEnd;
ULONG lBufferLength, lRowID, lRowIndex, lColumnID, lColumnNameCount, lColumnValueCount, lWord, lWordCount;
BOOL bReturn = FALSE;
/* query collection */
hFile = CreateFileW(GetDatabaseCollectionName(lpCollection[0]),
GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile != INVALID_HANDLE_VALUE) {
lBufferLength = GetFileSize(hFile, 0);
if (lBufferLength != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) {
pBuffer = (WCHAR *)Allocate("Collection read buffer", lBufferLength + sizeof(WCHAR));
if (pBuffer != 0) {
if (ReadFile(hFile, pBuffer, lBufferLength, &lBufferLength, 0)) {
lBufferLength = (lBufferLength / 2) + 1;
pBuffer[lBufferLength - 1] = L'\n';
/* seek entries */
for (pLine = pBuffer;(pCurrent = wmemchr(pLine, L'\n', pEnd - pCurrent)) != 0;pLine = &pCurrent[1]) {
pCurrent[(pLine > pCurrent && pCurrent[-1] == L'\r' ? -1 : 0] = L'\0';
pOpeningBrace[0] = wmemchr(pLine, L'{', pCurrent - pLine);
if (! pOpeningBrace[0]) {
/* no opening brace */
continue;
}
pClosingBrace[0] = wmemchr(&pOpeningBrace[0][1], L'}', pCurrent - &pOpeningBrace[0][1]);
if (! pClosingBrace[0]) {
/* no closing brace */
continue;
}
pOpeningBrace[1] = wmemchr(&pClosingBrace[0][1], L'{', pCurrent - &pClosingBrace[0][1]);
if (! pOpeningBrace[1]) {
/* no opening brace */
continue;
}
pClosingBrace[1] = wmemchr(&pOpeningBrace[1][1], L'}', pCurrent - &pOpeningBrace[1][1]);
if (! pClosingBrace) {
/* no closign brace */
continue;
}
pClosingBrace[0][0] = '\0';
pClosingBrace[1][0] = '\0';
/* remove heading and tailing spaces */
for (pWordEnd = pOpeningBrace[0];pWordEnd > pLine && iswspace(pWordEnd[-1]);--pWordEnd);
pWordEnd[0] = L'\0';
for (;pLine < pWordEnd && iswspace(pLine[0]);++pLine);
for (lRowID = 0;lRowID < GetDatabaseRowIDCount(lpDatabase);lRowID++) {
if (! wcsicmp(GetDatabaseRowName(lpDatabase, lRowID), pLine)) {
/* create row and get known columns */
lRowIndex = CreateCollectionRow(lpCollection[0], lRowID);
if (lRowIndex == INFINITE) {
/* error could not create row */
break;
}
/* tokenize strings */
wszColumnName = TokenizeCommaSeperatedString(&pOpeningBrace[0][1], &lColumnNameCount);
if (wszColumnName != 0) {
wszColumnValue = TokenizeCommaSeperatedString(&pOpeningBrace[1][1], &lColumnValueCount);
if (wszColumnValue != 0) {
/* get known columns */
lWordCount = min(lColumnNameCount, lColumnValueCount);
for (lColumnID = 0;lColumnID < GetDatabaseRowColumnCount(lpDatabase, lRowID);++lColumnID) {
for (lWord = 0;lWord < lWordCount;lWord++) {
if (! _wcsicmp(GetDatabaseRowColumnName(lpDatabase, lRowID, lColumnID), wszColumnName[n])) {
/* create value */
lpValue = CreateWStringValue(wszColumnValue[n]);
if (lpValue != 0) {
if (! SetCollectionRowColumnValue(lpCollection, lRowID, lRowIndex, lColumnID, lpValue)) {
FreeValue(lpValue);
}
}
break;
}
}
}
Free(wszColumnValue);
}
Free(wszColumnName);
}
break;
}
}
}
}
Free(pBuffer);
}
}
CloseHandle(hFile);
}
return bReturn;
}
BOOL DeleteCollection(LPDATABASE lpDatabase, LPDATABASE_COLLECTION lpCollection)
{
/* delete collection */
return DeleteFileW(GetDatabaseCollectionName(lpCollection));
}
BOOL CreateCollection(LPDATABASE lpDatabase, LPWSTR wszCollectionName)
{
HANDLE hFile;
BOOL bReturn = FALSE;
/* create collection */
hFile = CreateFileW(wszCollectionName,
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0;
if (hFile != INVALID_HANDLE_VALUE) {
bReturn = TRUE;
CloseHandle(hFile);
}
return bReturn;
}
BOOL Shutdown(LPDATABASE lpDatabase)
{
/* module shutdown */
return TRUE;
}
|