📄 sugarmemodb.c
字号:
if (record->field[WordFieldQuestion]!=NULL)
index += StrLen(record->field[WordFieldQuestion])+1;
if (record->field[WordFieldPhonetic]!=NULL)
index += StrLen(record->field[WordFieldPhonetic])+1;
if (record->field[WordFieldAnswer]!=NULL)
answerOffset = index;
DmWrite(recordDBEntry, (UInt32)&packed->answerOffset, &answerOffset, sizeof(answerOffset));
} //end of routine PackRecord
// unpack word record
static void UnpackRecord(WordPackedRecord *packed, WordRecordType *record){
Int16 index;
UInt16 flags;
char* p;
record->header = packed ->header;
record->ltStatus = packed ->ltStatus;
record->memoStatus = packed ->memoStatus;
flags = packed -> wordDBRecordFlags.allBits;
p = & packed -> firstField;
for (index = 0; index < WordFieldsCount; index ++){
if (GetBitMacro(flags, index) != 0){
record->field[index] = p;
p += StrLen(p) + 1;
}
else{
record->field[index] = NULL;
}
}
}
// callback funtion for compare records
static Int16 WordDBComparePackedRecords(WordPackedRecord* packed1, WordPackedRecord* packed2,
Int16 uselessinfo, SortRecordInfoPtr infoP1, SortRecordInfoPtr infoP2, MemHandle appinfoH){
//if both header remain their sequence
if ((GetBitMacro(packed1->header.allBits, HeaderFlag))
&& (GetBitMacro(packed2->header.allBits, HeaderFlag)))
return 0;
//otherwise the header record is less than the other one
if (GetBitMacro(packed1->header.allBits, HeaderFlag))
return -1;
if (GetBitMacro(packed2->header.allBits, HeaderFlag))
return 1;
//both word, and both no question field
if ((GetBitMacro(packed1->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
&& (GetBitMacro(packed2->wordDBRecordFlags.allBits, WordFieldQuestion) == 0))
return 0;
//both word, the one without question field is less than the other one
if (GetBitMacro(packed1->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
return -1;
if (GetBitMacro(packed2->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
return 1;
//both word and both have the question field, compare string
return StrCaselessCompare((char*)(&packed1->firstField), (char*)(&packed2->firstField));
}
// create new record
Err NewWordRecord(DmOpenRef db, WordRecordType* record, UInt16* index){
MemHandle recordH;
WordPackedRecord* packed;
UInt16 newIndex;
Err error;
//allocate new record size
recordH = DmNewHandle(db, WordUnpackedSize(record));
if (recordH == NULL) return dmErrMemError;
//copy the data from unpacked record to packed one
packed = MemHandleLock(recordH); //locked once
PackRecord(record, packed);
//get the index of new record
newIndex = DmFindSortPosition(db, packed, NULL, (DmComparF*)WordDBComparePackedRecords, NULL);
MemPtrUnlock(packed); //unlocked
//attach new record in place and return the new index
error = DmAttachRecord(db, &newIndex, recordH, NULL);
if (error)
MemHandleFree(recordH);
else
*index = newIndex;
return error;
}
// Get Word Record, noting that recordH is locked here, should be unlock else where!
Err GetWordRecord(DmOpenRef db, UInt16 index, WordRecordType* recordP, MemHandle *recordH)
{
WordPackedRecord *packed;
*recordH = DmQueryRecord(db, index);
packed = (WordPackedRecord *) MemHandleLock(*recordH);
if (packed == NULL)
return dmErrIndexOutOfRange;
UnpackRecord(packed, recordP);
return 0;
}
// Change Word Record
Err ChangeWordRecord(DmOpenRef dbP, UInt16 *index, WordRecordType* r, WordFieldFlags changedFields)
{
WordRecordType src;
MemHandle srcH;
Err error;
MemHandle recordH = 0; ///???
MemHandle oldH;
Int16 i;
UInt32 changes = changedFields.allBits;
Boolean dontMove;
UInt16 attributes; // to contain the deleted flag
WordPackedRecord* cmpP;
WordPackedRecord* recordP;
// We do not assume that r is completely valid so we get a valid
// WordRecordType*...
if ((error = GetWordRecord(dbP, *index, &src, &srcH)) != 0)
return error;
// and we apply the changes to it.
src.header = r->header; // copy the status
src.ltStatus = r->ltStatus;
src.memoStatus = r->memoStatus;
for (i = WordFieldQuestion; i < WordFieldsCount; i++)
{
// If the flag is set point to the string else NULL
if (GetBitMacro(changes, i) != 0)
{
src.field[i] = r->field[i];
RemoveBitMacro(changes, i);
}
if (changes == 0)
break; // no more changes
}
// 1) and 2) (make a new chunk with the correct size)
recordH = DmNewHandle(dbP, WordUnpackedSize(&src));
if (recordH == NULL)
{
MemHandleUnlock(srcH); // undo lock from GetWordRecord above
return dmErrMemError;
}
recordP = MemHandleLock(recordH);
// 3) Copy the data from the unpacked record to the packed one.
PackRecord(&src, recordP);
// The original record is copied and no longer needed.
MemHandleUnlock(srcH);
// 4) if the sort position changes...
// Check if question field has changed
if ((changedFields.allBits & BitAtPosition(WordFieldQuestion)) == 0)
goto attachRecord;
// Make sure *index-1 < *index < *index+1, if so it's in sorted
// order. Leave it there.
//appInfoPtr = (SugarAppInfoType*) GetAppInfoPtr(dbP);
//sortByCompany = appInfoPtr->misc.sortByCompany;
//MemPtrUnlock(appInfoPtr);
if (*index > HeaderIndexCounts)
{
// This record wasn't deleted and deleted records are at the end of the
// database so the prior record may not be deleted!
cmpP = MemHandleLock(DmQueryRecord(dbP, *index-1));
dontMove = (WordDBComparePackedRecords (cmpP, recordP, NULL, NULL, NULL, 0) < 0);
MemPtrUnlock(cmpP);
}
else
dontMove = true;
if (*index+1 < DmNumRecords (dbP))
{
DmRecordInfo(dbP, *index+1, &attributes, NULL, NULL);
if (attributes & dmRecAttrDelete)
; // don't move it after the deleted record!
else {
cmpP = MemHandleLock(DmQueryRecord(dbP, *index+1));
dontMove = dontMove && (WordDBComparePackedRecords (recordP, cmpP, NULL, NULL, NULL, 0) == -1);
MemPtrUnlock(cmpP);
}
}
if (dontMove)
goto attachRecord;
// The record isn't in the right position. Move it.
i = DmFindSortPosition(dbP, recordP, NULL, (DmComparF*)WordDBComparePackedRecords, NULL);
DmMoveRecord(dbP, *index, i);
if (i > *index) i--;
*index = i; // return new position
// Attach the new record to the old index, the preserves the
// category and record id.
attachRecord:
error = DmAttachRecord(dbP, index, recordH, &oldH);
MemPtrUnlock(recordP);
if (error) return error;
MemHandleFree(oldH);
return 0;
}
// delete word record
void WordDBDeleteRecord(Boolean archive){
HeaderQueue queue = GetQueue(CurrentDB, CurrentRecord);
if (queue == RawQueue) DecrementRawWordCount();
if (queue == LearningQueue) RemoveHeaderItemByDBIndex(CurrentDB, LearningRecordIndex, CurrentRecord);
if (queue == TestingQueue) RemoveHeaderItemByDBIndex(CurrentDB, TestingRecordIndex, CurrentRecord);
RemoveHeaderItemByDBIndex(CurrentDB, TestingChoiceBuffer, CurrentRecord);
RemoveHeaderItemByDBIndex(CurrentDB, LearningChoiceBuffer, CurrentRecord);
if (archive)
{
DmArchiveRecord (CurrentDB, CurrentRecord);
}
else
DmRemoveRecord (CurrentDB, CurrentRecord);
CurrentRecord = noRecord;
}
//*******************************************************************
//
// high-level word record manipulation
// 1.GetQueue();
// 2.SetQueue(HeaderQueue queue);
// 3.GetLearningStatus();
// 4.SetLearningStatus(LearningStatus ls);
// 5.GetTestingStatus();
// 6.SetTestingStatus(TestingStatus ls);
// 7.GetMemorizingStatus();
// 8.SetmemorizingStatus(MemorizingStatus memoStatus);
//
//*******************************************************************
// Get CurrentRecord Queue
HeaderQueue GetQueue(DmOpenRef db, UInt16 index){
HeaderQueue queue;
Header* header;
MemHandle recordH;
recordH = DmQueryRecord(db, index);
if (recordH == NULL) return BadQueue;
header = MemHandleLock(recordH);
if (GetBitMacro(header->allBits, RawQueue)) queue = RawQueue;
else if (GetBitMacro(header->allBits, LearningQueue)) queue = LearningQueue;
else if (GetBitMacro(header->allBits, TestingQueue)) queue = TestingQueue;
else if (GetBitMacro(header->allBits, WaitingQueue)) queue = WaitingQueue;
else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, LearningQFlag))
queue = LearningQFlag;
else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, TestingQFlag))
queue = TestingQFlag;
else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, LearningBFlag))
queue = LearningBFlag;
else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, TestingBFlag))
queue = TestingBFlag;
MemHandleUnlock(recordH);
return queue;
}
// Set CurrentRecord Queue
void SetQueue(DmOpenRef db, UInt16 index, HeaderQueue queue){
WordFieldFlags flag;
WordRecordType record;
MemHandle recordH;
HeaderQueue oldQueue;
oldQueue = GetQueue(db, index);
if (oldQueue == queue) return;
// remove from old header Q
if (oldQueue == LearningQueue) RemoveHeaderItemByDBIndex(db, LearningRecordIndex, index);
if (oldQueue == TestingQueue) RemoveHeaderItemByDBIndex(db, TestingRecordIndex, index);
// add to new header Q
if (queue == LearningQueue) AddHeaderItemByDBIndex(db, LearningRecordIndex, index);
if (queue == TestingQueue) AddHeaderItemByDBIndex(db, TestingRecordIndex, index);
// update raw word count
if (oldQueue == RawQueue) DecrementRawWordCount();
if (queue == RawQueue) IncrementRawWordCount();
flag.allBits = 0;
GetWordRecord(db, index, &record, &recordH);
record.header.allBits = BitAtPosition(queue);
ChangeWordRecord(db, &index, &record, flag);
}
// Get learning status of CurrentRecord
LearningStatus GetLearningStatus(DmOpenRef db, UInt16 index){
WordRecordType record;
MemHandle recordH;
LearningStatus status;
GetWordRecord(db, index, &record, &recordH); //lock recordH
status = record.ltStatus.learningStatus;
MemHandleUnlock(recordH);
return status;
}
// Set learning status of CurrentRecord
void SetLearningStatus(DmOpenRef db, UInt16 index, LearningStatus ls){
WordFieldFlags flag;
WordRecordType record;
MemHandle recordH;
GetWordRecord(db, index, &record, &recordH);
record.ltStatus.learningStatus = ls;
flag.allBits = 0;
ChangeWordRecord(db, &index, &record, flag);
}
// Get testing status of CurrentRecord
TestingStatus GetTestingStatus(DmOpenRef db, UInt16 index){
WordRecordType record;
MemHandle recordH;
TestingStatus status;
GetWordRecord(db, index, &record, &recordH); //lock recordH
status = record.ltStatus.testingStatus;
MemHandleUnlock(recordH);
return status;
}
// Set testing status of CurrentRecord
void SetTestingStatus(DmOpenRef db, UInt16 index, TestingStatus ts){
WordFieldFlags flag;
WordRecordType record;
MemHandle recordH;
GetWordRecord(db, index, &record, &recordH);
record.ltStatus.testingStatus = ts;
flag.allBits = 0;
ChangeWordRecord(db, &index, &record, flag);
}
// Get memorizing status of CurrentRecord
MemorizingStatus GetMemorizingStatus(DmOpenRef db, UInt16 index){
WordRecordType record;
MemHandle recordH;
MemorizingStatus memoStatus;
GetWordRecord(db, index, &record, &recordH);
memoStatus = record.memoStatus;
MemHandleUnlock(recordH);
return memoStatus;
}
// Set memorizing status of CurrentRecord
void SetMemorizingStatus(DmOpenRef db, UInt16 index, MemorizingStatus memoStatus){
WordRecordType record;
MemHandle recordH;
WordFieldFlags flag;
flag.allBits = 0;
GetWordRecord(db, index, &record, &recordH);
record.memoStatus = memoStatus;
ChangeWordRecord(db, &index, &record, flag);
}
//*******************************************************************
//
// Misc function relating to database manipulation
// 1.GetDBList();
// 2.WordRecordContainsData (WordRecordType* recordP);
// 3.InstantLookupPosition(DmOpenRef db, Char* p);
// 4.GetWordQueue(DmOpenRef db, UInt16 index);
//
//*******************************************************************
// Buil
void InitHeaderBuffer(DmOpenRef db, HeaderIndex BufferIndex){
MemHandle srcH, destH;
HeaderRecord* srcP, *destP;
MemPtr offsetP;
UInt16 bufferNum, srcHeaderIndex, destHeaderIndex; // index; //, i, j;
UInt32 newSize;
//HeaderItem item;
//Err error;
// validate
//bufferNum = GetHeaderItemNumber(db, BufferIndex);
//for (i = 0; i < bufferNum; i++){
//j = bufferNum -i - 1;
//if (!GetHeaderItem(db, BufferIndex, &item, j)) continue;
//error = DmFindRecordByID(db, item, &index);
//if (error) RemoveHeaderItem(db, BufferIndex, bufferNum - i - 1);
//}
bufferNum = GetHeaderItemNumber(db, BufferIndex);
if (bufferNum > 0) return;
if (BufferIndex == LearningChoiceBuffer){
srcHeaderIndex = LearningRecordIndex;
destHeaderIndex = LearningChoiceBuffer;
}
else if (BufferIndex == TestingChoiceBuffer){
if (GetHeaderItemNumber(db, LearningChoiceBuffer) > 0)
srcHeaderIndex = LearningChoiceBuffer;
else if (GetHeaderItemNumber(db, TestingRecordIndex) > 0)
srcHeaderIndex = TestingRecordIndex;
destHeaderIndex = TestingChoiceBuffer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -