📄 ndb.c
字号:
/********************************************************************** FILE: NDB.c** DESCRIPTION: The Starter project module.** VERSION: 1.0**********************************************************************/#include <PalmOS.h>#include <PalmCompatibility.h>#include "NDB.h"#include "NDBpriv.h"// Macros// Extract the bit at position index from bitfield. 0 is the high bit.#define BitAtPosition(pos) ((UInt32)1 << (pos))#define GetBitMacro(bitfield, index) ((bitfield) & BitAtPosition(index))#define SetBitMacro(bitfield, index) ((bitfield) |= BitAtPosition(index))#define RemoveBitMacro(bitfield, index) ((bitfield) &= ~BitAtPosition(index))// member variablesstatic NDBDmOpenDatabaseType ndbOpenDB[ ndbLastDatabase ] = { 0 };// constant definitions -- type & creator codes for opening databasesstatic UInt32 ndbDatabaseType[] = { 0, addrDBType, memoDBType, datebookDBType, toDoDBType };static UInt32 ndbDatabaseCreator[] = { 0, sysFileCAddress, sysFileCMemo, sysFileCDatebook, sysFileCToDo };#define NDBMAXDESCLEN ( 64 )// private functions/******************************************************************** * FUNCTION: NDBNewHandleFromString * * DESCRIPTION: This routine creates a new handle given * a string with a copy of the string * * RETURNED: MemHandle to copy of string. Caller frees * error code at the location specified * by errP.**********************************************************************/static MemHandle NDBNewHandleFromString // (out) string copy( CharPtr string, Err *errP // (in) where to place error) // (out) error code for error{ MemHandle resultH; CharPtr resultP; *errP = noErr;// validate input if ( string == NULL ) *errP = dmErrInvalidParam; // create result handle if ( *errP == noErr ) resultH = MemHandleNew( StrLen( string ) + 1 ); if ( resultH == NULL ) *errP = memErrNotEnoughSpace;// lock result handle if ( *errP == noErr ) resultP = MemHandleLock( resultH ); // Copy the string if ( *errP == noErr ) StrCopy( resultP, string ); // Unlock the handle if ( resultP ) MemHandleUnlock( resultH );// Return the copy return resultH;}/******************************************************************** * FUNCTION: NDBFetchStringFromPackedRecord * * DESCRIPTION: This routine fetches the indicated string * from the run of contiguous null-terminated * strings. * * RETURNED: Pointer to string**********************************************************************/static CharPtr NDBFetchStringFromPackedRecord // (out) string( CharPtr startP, // (in) Start of region UInt16 index, // (in) which to get UInt16 count // (in) how many there are){ CharPtr resultP = startP; int i;// validate if ( startP == NULL ) return ndbEmptyString; if ( index >= count ) return ndbEmptyString;// Find the index'th string. for ( i = 0; i < index; i++ ) resultP += StrLen( resultP ) + sizeof( Char ); // Don't forget the null! return resultP;}/******************************************************************** * FUNCTION: NDBFetchStringFromPackedMaskRecord * * DESCRIPTION: This routine fetches the indicated string * from the run of contiguous null-terminated * strings. * * RETURNED: Pointer to string**********************************************************************/static CharPtr NDBFetchStringFromPackedMaskRecord // (out) string( CharPtr startP, // (in) Start of region UInt16 index, // (in) which to get UInt16 count, // (in) how many there are UInt32 flags // (in) which strings are there){ CharPtr resultP = startP; int i;// validate if ( startP == NULL ) return ndbEmptyString; else if ( index >= count ) return ndbEmptyString;// If this string isn't in the packed set, just say so and return an empty string. else if ( GetBitMacro( flags, index ) == 0 ) return ndbEmptyString; else// Find the index'th string. for ( i = 0; i < index; i++ ) if ( GetBitMacro( flags, i ) != 0 ) resultP += StrLen( resultP ) + sizeof( Char ); // Don't forget the null! return resultP;}/******************************************************************** * FUNCTION: NDBOpenDatabase * * DESCRIPTION: This routine opens the desired database * and increments the reference count * associted with the given database. * If the database is already open, a * handle to it is returned and the * reference count incremented. * SIDE EFFECT: This routine manipulates entries * in the ndbOpenDB array. * * RETURNED: nothing * error code at the location specified * by errP. One of * dmErrInvalidDatabaseName - no such database * dmErrIndexOutOfRange - bad db specified**********************************************************************/static void NDBOpenDatabase // (out) nothing( NDBDatabaseEnum db, // (in) database to open Err *errP // (in) where to place error) // (out) error code for error{ DmOpenRef dbRef = NULL; LocalID dbId; UInt16 card; *errP = noErr; // validate incoming arguments if ( db <= ndbInvalid || db >= ndbLastDatabase ) *errP = dmErrIndexOutOfRange; if ( *errP == noErr ) {// If the database is open, increment the reference count. if ( ndbOpenDB[ db ].refCount > 0 ) { ndbOpenDB[ db ].refCount++; } else {// Try to open the database on each card.// First, find the database's ID. dbRef = DmOpenDatabaseByTypeCreator( ndbDatabaseType[ db ], ndbDatabaseCreator[ db ], dmModeReadOnly ); if ( dbRef == NULL ) *errP = dmErrInvalidDatabaseName; if ( *errP == noErr ) {// Get the LocalID of the database so we can open it on all cards. DmOpenDatabaseInfo ( dbRef, &dbId, NULL, NULL, NULL, NULL );// Close the database DmCloseDatabase( dbRef ); } if ( *errP == noErr ) {// Now, loop over all cards and get an open database for each. for ( card = 0; card < ndbMaxCardNum; card++ ) { if ( DmNumDatabases( card ) > 0 ) ndbOpenDB[ db ].dbRef[ card ] = DmOpenDatabase ( (UInt16)card, dbId, (UInt16)(dmModeReadOnly | dmModeShowSecret) ); } // And set the reference count to 1, because there's one caller. ndbOpenDB[ db ].refCount = 1; } } } return;}/******************************************************************** * FUNCTION: NDBCloseDatabase * * DESCRIPTION: This routine closes the indicated * database on all cards. If the database's * reference count indicates that it's still * in use, we simply decrement the reference * count; otherwise we close the database as * well. * * RETURNED: Nothing * error code at the location specified * by errP. One of * dmErrIndexOutOfRange - bad db specified**********************************************************************/static void NDBCloseDatabase // (out) nothing( NDBDatabaseEnum db, // (in) database to open Err *errP // (in) where to place error) // (out) error code for error{ int card; *errP = noErr; // validate incoming arguments if ( db <= ndbInvalid || db >= ndbLastDatabase ) *errP = dmErrIndexOutOfRange; if ( *errP == noErr ) {// If the database is open, decrement the reference count. if ( ndbOpenDB[ db ].refCount > 0 ) { ndbOpenDB[ db ].refCount--; } else { *errP = dmErrNoOpenDatabase; } } // If the reference count now indicates that there is nobody// else that needs this database, close the database on each card if ( *errP == noErr ) { if ( ndbOpenDB[ db ].refCount == 0 ) {// Loop over all cards and close the database for each. for ( card = 0; card < ndbMaxCardNum; card++ ) {// Only try to close those databases that were opened, of course. if ( ndbOpenDB[ db ].dbRef[ card ] ) { DmCloseDatabase ( ndbOpenDB[ db ].dbRef[ card ] ); ndbOpenDB[ db ].dbRef[ card ] = NULL; } } } } return ;}/******************************************************************** * FUNCTION: NDBDatabaseRefForDatabase * * DESCRIPTION: This routine returns the array o * SIDE EFFECT(S): This routine * * RETURNED: Pointer to first of ndbMaxCardNum * open database references * error code at the location specified * by errP.**********************************************************************/static DmOpenRef *NDBDatabaseRefForDatabase // (out) db ptr( NDBDatabaseEnum db, // (in) database sought Err *errP // (in) where to place error) // (out) error code for error{ DmOpenRef *dbP = NULL; *errP = noErr;// validate incoming arguments if ( db <= ndbInvalid || db >= ndbLastDatabase ) *errP = dmErrIndexOutOfRange; if ( *errP == noErr ) {// If the database is open, return it, otherwise return NULL. if ( ndbOpenDB[ db ].refCount > 0 ) { dbP = ndbOpenDB[ db ].dbRef; } } return dbP;}/******************************************************************** * FUNCTION: NDBMemSearch * * DESCRIPTION: This routine searches a block of memory * for the desired subfield. * * RETURNED: pointer to the location of the first * occurence of the subfield, or NULL**********************************************************************/static BytePtr NDBMemSearch // (out) pointer to substr( BytePtr field, // (in) field to search BytePtr sub, // (in) subfield to find UInt32 szField, // (in) size of field UInt32 szSub // (in) size of subfield){ Boolean found = false; UInt32 i, j; BytePtr res = NULL; // for each byte in the field... for ( i = 0; i < szField; i++ ) {// if that byte matches the current byte of the subfield if ( field[i] == sub[j] ) { j++;// move ahead to check the next byte of the subfield if ( j == szSub ) {// No more bytes... we've found it! found = true; res = &field[i-szSub]; break; } } else {// Hmm. It didn't match the current byte of the target, so reset j = 0; } } return res;}/******************************************************************** * FUNCTION: NDBNextSearchByString * * DESCRIPTION: This routine looks for the next record * containing the desired string. * SIDE EFFECT(S): This routine modifies the fields of * recordP. * * RETURNED: nothing * error code at the location specified * by errP. One of: * ndbErrorSearchOver - search complete**********************************************************************/static void NDBNextSearchByString // (out) nothing( NDBRecordType *recordP, // (in) record to search for Err *errP, // (in) where to place error NDBSearchDirEnum dir // (in) which way to go) // (out) error code for error{ BytePtr bP; Boolean found; *errP = noErr;// validate arguments if ( recordP != NULL ) *errP = dmErrInvalidParam;// Loop over index to find the next matching record. do {// Find the next record recordP->recordH = NDBGetRecordWithIndex ( recordP->database, recordP->recordIdx, errP ); if ( recordP->recordH != NULL ) { bP = (BytePtr)MemHandleLock( recordP->recordH );// Does this record have the desired substring? found = (Boolean)( NDBMemSearch ( (BytePtr)bP, (BytePtr)recordP->targetP, MemHandleSize ( (MemHandle)recordP->recordH ), (UInt32)StrLen ( recordP->targetP ) ) != NULL ); MemHandleUnlock( recordP->recordH );// Yep. if ( found ) break;// Nope. Are we at the beginning? If so, quit. if ( dir == ndbSearchPrev && recordP->recordIdx == 0 ) break; // Nope. Look at the next record. recordP->recordIdx+= dir; recordP->recordH = NULL; } } while ( *errP == noErr );// If it's not found, say so. if ( !found ) { recordP->recordH = NULL; if ( dir == ndbSearchNext ) *errP = ndbErrorSearchOver; else *errP = ndbErrorNoPreviousRecord; } return;}/******************************************************************** * FUNCTION: NDBRecordNew * * DESCRIPTION: This routine allocates a new NDBRecord. * SIDE EFFECT: None * * RETURNED: Handle to new record * error code at the location specified * by errP. One of * memErrNotEnoughSpace - not enough memory * memErrChunkNotLocked - could not lock **********************************************************************/static MemHandle NDBRecordNew // (out) handle to new record( NDBDatabaseEnum db, // (in) database to search CharPtr keyP, // (in) search key Err *errP // (in) where to place error) // (out) error code for error{ MemHandle resultH; NDBRecordType *resultP; CharPtr tempP = NULL; *errP = noErr; // Allocate memory resultH = MemHandleNew( sizeof ( NDBRecordType ) ); if ( !resultH ) *errP = memErrNotEnoughSpace; if ( *errP == noErr && keyP ) tempP = MemPtrNew( StrLen( keyP ) + 1 ); if ( keyP && tempP == NULL ) *errP = memErrNotEnoughSpace; if ( *errP == noErr ) resultP = MemHandleLock( resultH );// Initialize fields. if ( *errP == noErr ) { resultP->database = db; resultP->targetP = tempP; if ( keyP ) StrCopy( resultP->targetP, keyP ); resultP->recordIdx = 0;// Unlock MemHandleUnlock( resultH ); } return resultH;}/******************************************************************** * FUNCTION: NDBGetRecordWithIndex * * DESCRIPTION: This routine retrieves the record * at the virtual index specified. * * RETURNED: The record or NULL. * error code at the location specified * by errP. One of * dmErrIndexOutOfRange - db invalid * **********************************************************************/static MemHandle NDBGetRecordWithIndex ( // (out) handle to data NDBDatabaseEnum db, // (in) what database? UInt16 index, // (in) which record? Err *errP // (in) where to place error) // (out) error code for error{ MemHandle dataH = NULL; DmOpenRef *databaseP; DmOpenRef theDatabase; UInt16 theCard; UInt16 theIndex = index; UInt32 recCountOnCard = 0; LocalID dbID; Boolean found = false; *errP = noErr;// validate arguments if ( db <= ndbInvalid || db >= ndbLastDatabase ) *errP = dmErrIndexOutOfRange; databaseP = NDBDatabaseRefForDatabase( db, errP ); if (*errP == noErr ) for ( theCard = 0; theCard < ndbMaxCardNum; theCard++ ) { theDatabase = databaseP[ theCard ];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -