📄 sugarmemodb.c
字号:
RemoveHeaderItem(db, headerIndex, random);
i++;
number--;
}
error = DmAttachRecord(db, &headerIndex, recordH, &oldH);
MemPtrUnlock(destP);
if (error){
MemHandleFree(recordH);
return false;
}
MemHandleFree(oldH);
return true;
}*/
//remove the i th item in queue
Boolean RemoveHeaderItem(DmOpenRef db, HeaderIndex headerIndex, UInt16 i){
MemHandle recordH, oldH;
MemPtr destP;
HeaderItem* itemP;
HeaderRecordHelper* srcP;
HeaderRecordHelper* p = 0;
UInt16 numbers, size, newSize, offset;
Err error;
//calculate newsize
numbers = GetHeaderItemNumber(db, headerIndex);
size = sizeof(HeaderRecord) + numbers * sizeof(HeaderItem);
newSize = size - sizeof(HeaderItem);
//get original learning record
srcP = (HeaderRecordHelper*)MemHandleLock(DmQueryRecord(db, headerIndex)); //src locked
//allocate new record
recordH = DmNewHandle(db, newSize);
if (recordH == NULL) return false;
destP = MemHandleLock(recordH); //dest locked
//copy original data before item i
DmWrite(destP, 0, srcP, sizeof(HeaderRecord) + i * sizeof(HeaderItem));
//copy orginal data after item i, if any
if (i != (numbers - 1)){
itemP = &srcP->firstItem;
itemP += i + 1;
offset = (UInt32)&p->firstItem + i * sizeof(HeaderItem);
DmWrite(destP, offset, itemP, (numbers - i - 1) * sizeof(HeaderItem));
}
//write new number
numbers--;
DmWrite(destP, (UInt32)&p->itemNumbers, &numbers, sizeof(numbers));
//unlock src pointer
MemPtrUnlock(srcP);
//attach new record
error = DmAttachRecord(db, &headerIndex, recordH, &oldH);
//unlock dest pointer
MemPtrUnlock(destP);
if (error) {
MemHandleFree(recordH);
return false;
}
//release orphan data
MemHandleFree(oldH);
return true;
}
//
Boolean FindHeaderItemByID(DmOpenRef db, HeaderIndex headerIndex, UInt32 uniqueID, UInt16* indexP){
MemHandle recordH;
HeaderRecordHelper* recordP;
HeaderItem* p;
UInt16 numbers, i = 0;
Boolean found = false;
recordH = DmQueryRecord(db, headerIndex);
if (recordH == NULL) return false;
recordP = (HeaderRecordHelper*)MemHandleLock(recordH);
numbers = recordP -> itemNumbers;
p = &recordP -> firstItem;
while (i < numbers){
if ((UInt32)(*p)== uniqueID) {
found = true;
break;
}
p++;
i++;
}
MemPtrUnlock(recordP);
if (found) {
(*indexP) = i;
return true;
}
return false;
}
Boolean FindHeaderItemByDBIndex(DmOpenRef db, HeaderIndex headerIndex, UInt16 dbIndex, UInt16* indexP){
HeaderItem item;
DmRecordInfo(db, dbIndex, NULL, &item, NULL);
return FindHeaderItemByID(db, headerIndex, item, indexP);
}
// remove header item according item content, i.e. unique ID
Boolean RemoveHeaderItemByID(DmOpenRef db, HeaderIndex headerIndex, UInt32 uniqueID){
UInt16 i;
if (FindHeaderItemByID(db, headerIndex, uniqueID, &i)) return RemoveHeaderItem(db, headerIndex, i);
return false;
}
//remove header item by database index
Boolean RemoveHeaderItemByDBIndex(DmOpenRef db, HeaderIndex headerIndex, UInt16 dbIndex){
HeaderItem item;
DmRecordInfo(db, dbIndex, NULL, &item, NULL);
return RemoveHeaderItemByID(db, headerIndex, item);
}
//remove the first one, insert it into certain position, the status changed in LTStatus
Boolean MoveHeaderItem(DmOpenRef db, HeaderIndex headerIndex, UInt16 index){
MemHandle recordH;
HeaderRecordHelper* recordP;
HeaderItem* p;
HeaderItem item0;
UInt16 i;
//check index range
if (index > GetHeaderItemNumber(db, headerIndex) - 1)
index = GetHeaderItemNumber(db, headerIndex) - 1;
//save first item
GetHeaderItem(db, headerIndex, &item0, 0);
recordH = DmQueryRecord(db, headerIndex);
if (recordH == NULL) return false;
recordP = (HeaderRecordHelper*)MemHandleLock(recordH);
//point to item 1, the second item
p = &recordP -> firstItem;
p++; //pointer to item 1
//move
for (i = 0; i < index; i++){
DmWrite(recordP, (sizeof(HeaderRecord) + i * sizeof(HeaderItem)), p, sizeof(HeaderItem));
p++;
}
//restore first item
DmWrite(recordP, (sizeof(HeaderRecord) + index * sizeof(HeaderItem)), &item0, sizeof(HeaderItem));
MemPtrUnlock(recordP);
return true;
}
// rebuild testing queue
void RebuildTestingQueue(DmOpenRef db, Boolean forced){
UInt16 j, num;
UInt16 rawWordCount = 0;
DateType today;
WordPackedRecord* packed;
MemHandle recordH;
HeaderItem item;
SugarAppInfoType* app;
SugarAppInfoType* appHelper = 0;
Header flag;
UInt32 progress = 0;
UInt32 newProgress;
Char title[dmDBNameLength + 20];
Char dbName[dmDBNameLength + 1] = "Unknown";
LocalID localID;
Err error;
DateSecondsToDate(TimGetSeconds(), &today);
app = GetAppInfoPtr(db);
if (app == NULL) {
DoCustomDialog("错误", "无法打开AppInfo", false, 0, NULL, false);;
return;
}
if (!forced){
if (DateToDays(app->lastUpdated) == DateToDays(today)) {
MemPtrUnlock(app);
return;
}
}
ClearHeaderRecord(db, TestingRecordIndex);
//loop records
num = DmNumRecordsInCategory(db, dmAllCategories);
if (num > FirstWordRecord) {
error = DmOpenDatabaseInfo(db, &localID, NULL, NULL, NULL, NULL);
if (error) ErrAlert(error);
else {
error = DmDatabaseInfo(0, localID, dbName, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
if (error) ErrAlert(error);
else StrPrintF(title, "%s %s", "Updating", dbName);
}
ProgressPie(progress, title);
}
for (j = FirstWordRecord; j < num; j++){
recordH = DmQueryRecord(db, j);
if (recordH == NULL) ErrAlert(DmGetLastErr());
else {
packed = MemHandleLock(recordH);
flag.allBits = packed -> header.allBits;
if (GetBitMacro(flag.allBits, RawQueue)) {
MemHandleUnlock(recordH);
rawWordCount ++;
}
else if (GetBitMacro(flag.allBits, TestingQueue)){
MemHandleUnlock(recordH);
DmRecordInfo(db, j, NULL, &item, NULL);
AddHeaderItem(db, TestingRecordIndex, &item);
}
else if (GetBitMacro(flag.allBits, WaitingQueue)){
// if set queue before unlock mem, free handle error !
if (DateToDays(packed -> memoStatus.nextTest) <= DateToDays(today)){
MemHandleUnlock(recordH);
SetQueue(db, j, TestingQueue);
//DmRecordInfo(db, j, NULL, &item, NULL);
//AddHeaderItem(db, TestingRecordIndex, &item);
}
else MemHandleUnlock(recordH);
}
//MemHandleUnlock(recordH);
}
newProgress = (j - 1) * ProgressFull / (num - FirstWordRecord);
if (newProgress != progress) {
progress = newProgress;
ProgressPie(progress, title);
}
}
ShuffleHeaderItem(db, TestingRecordIndex);
//updage sugar db app info
DmWrite(app, (UInt32)&appHelper->lastUpdated, &today, sizeof(today));
DmWrite(app, (UInt32)&appHelper->rawWordCount, &rawWordCount, sizeof(rawWordCount));
MemPtrUnlock(app);
}
// rebuild learning queue
void RebuildLearningQueue(DmOpenRef db){
MemHandle recordH;
WordPackedRecord* packed;
WordPackedRecord* helper = 0;
LearningStatus ls = FirstLook;
HeaderItem item;
UInt16 j;
UInt16 num;
//clear Learing record
ClearHeaderRecord(db, LearningRecordIndex);
//loop records
num = DmNumRecordsInCategory(db, dmAllCategories);
for (j = FirstWordRecord; j < num; j++){
recordH = DmQueryRecord(db, j);
packed = MemHandleLock(recordH);
if (GetBitMacro(packed->header.allBits, LearningQueue)){
DmRecordInfo (db, j, NULL, &item, NULL);
AddHeaderItem(db, LearningRecordIndex, &item);
DmWrite(packed, (UInt32)&helper -> ltStatus.learningStatus, &ls, sizeof (LearningStatus));
}
MemHandleUnlock(recordH);
}
}
void ResetDatabase(DmOpenRef db){
SugarAppInfoType* app;
SugarAppInfoType* helper = 0;
WordPackedRecord packed;
MemHandle recordH;
MemPtr p;
UInt16 j, num;
UInt32 progress = 0;
UInt32 newProgress;
char progressTitle[20] = "Clearing....";
MemSet(&packed, sizeof(packed), 0);
SetBitMacro(packed.header.allBits, RawQueue);
packed.memoStatus.eFactor = 2.5;
packed.memoStatus.difficulty = 40;
app = GetAppInfoPtr(db);
num = DmNumRecordsInCategory(db, dmAllCategories);
if (num > FirstWordRecord) ProgressPie(progress, progressTitle);
for (j = FirstWordRecord; j < num; j++){
recordH = DmQueryRecord(db, j);
p = MemHandleLock(recordH);
DmWrite(p, 0, &packed,
//header + LTStatus + MemorizingStatus - CreateDate (createDate not changed)
sizeof(Header) + sizeof(LTStatus) + sizeof(MemorizingStatus) - sizeof(DateType));
MemHandleUnlock(recordH);
newProgress = (j - 1) * ProgressFull / (num - FirstWordRecord);
if (newProgress != progress) {
progress = newProgress;
ProgressPie(progress, progressTitle);
}
}
if (num > FirstWordRecord) num -= FirstWordRecord;
else num = 0;
DmWrite(app, (UInt32)&helper -> rawWordCount, &num, sizeof(num));
MemPtrUnlock(app);
ClearHeaderRecord(db, LearningRecordIndex);
ClearHeaderRecord(db, TestingRecordIndex);
ClearHeaderRecord(db, LearningChoiceBuffer);
ClearHeaderRecord(db, TestingChoiceBuffer);
}
//*******************************************************************
//
// Word record manipulation
// 1.WordUnpackedSize(WordRecordType *record);
// 2.PackRecord(WordRecordType *record, MemPtr recordDBEntry);
// 3.UnpackRecord(WordPackedRecord *packed, WordRecordType *record);
// 4.WordDBComparePackedRecords(WordPackedRecord * packed1, WordPackedRecord * packed2,
// Int16 uselessinfo, SortRecordInfoPtr infoP1, SortRecordInfoPtr infoP2, MemHandle appinfoH);
//
// 5.NewWordRecord(DmOpenRef db, WordRecordType* record, UInt16* index);
// 6.GetWordRecord(DmOpenRef db, UInt16 index, WordRecordType* recordP, MemHandle *recordH);
// 7.WordDBDeleteRecord(Boolean archive);
// 8.ChangeWordRecord(DmOpenRef dbP, UInt16 *index, WordRecordType* r, WordFieldFlags changedFields);
//
//*******************************************************************
// calculate the unpacked record size
static UInt16 WordUnpackedSize(WordRecordType *record){
UInt16 size;
int i;
//initial size is the size of a packed record, minus a placeholder of first field
size = sizeof(WordPackedRecord) - sizeof(char);
for (i = 0; i < WordFieldsCount; i++){
if (record->field[i] != NULL)
size += StrLen(record->field[i])+1;
}
return size;
}
// pack a record
static void PackRecord(WordRecordType *record, MemPtr recordDBEntry){
UInt32 offset;
Int16 index;
UInt16 length;
MemPtr p;
WordFieldFlags flags;
WordPackedRecord *packed = 0; //set the pointer to zero! this pointer is used to calculate offset position,
//NEVER try to use this pointer to access data, will cause fatal error!
UInt16 answerOffset = 0;
flags.allBits = 0;
//write wordstatus first, noting that (UInt32)&packed->wordStatus convert the reference pointer to a UInt32 number,
//since the packed address is originally set to zero, &packed->wordStatus point to the starting position of
//wordStatus, which is zero also at this time. Dangerous but efficient usage!
DmWrite(recordDBEntry, (UInt32)&packed->header, &record->header, sizeof(record->header));
DmWrite(recordDBEntry, (UInt32)&packed->ltStatus, &record->ltStatus, sizeof(record->ltStatus));
DmWrite(recordDBEntry, (UInt32)&packed->memoStatus, &record->memoStatus, sizeof(record->memoStatus));
//pointer to first field placeholder
offset = (UInt32)&packed->firstField;
//write all fields into record and set the flag bit
for (index = WordFieldQuestion; index < WordFieldsCount; index++){
if (record->field[index]!=NULL){
p = record->field[index];
length = StrLen(p)+1;
DmWrite(recordDBEntry, offset, p, length);
offset += length;
SetBitMacro(flags.allBits, index);
}
} //end of loop
//write flags
DmWrite(recordDBEntry, (UInt32)&packed->wordDBRecordFlags, &flags.allBits, sizeof(flags.allBits));
//set or clear field offset
index = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -