static char *SerializePrefs(SerializableGlobalPrefs& globalPrefs, FileHistory& root, Favorites *favs, size_t* lenOut) { char *data = NULL; BencDict *prefs = new BencDict(); if (!prefs) goto Error; BencDict* global = SerializeGlobalPrefs(globalPrefs); if (!global) goto Error; prefs->Add(GLOBAL_PREFS_STR, global); BencArray *fileHistory = SerializeFileHistory(root, globalPrefs.globalPrefsOnly); if (!fileHistory) goto Error; prefs->Add(FILE_HISTORY_STR, fileHistory); BencArray *favsArr = SerializeFavorites(favs); if (!favsArr) goto Error; prefs->Add(FAVS_STR, favsArr); data = prefs->Encode(); *lenOut = str::Len(data); Error: delete prefs; return data; }
BencDict *BencDict::Decode(const char *bytes, size_t *lenOut) { if (!bytes || *bytes != 'd') return NULL; BencDict *dict = new BencDict(); size_t ix = 1; while (bytes[ix] != 'e') { size_t len; BencString *key = BencString::Decode(bytes + ix, &len); if (!key || key->Type() != BT_STRING) { delete key; delete dict; return NULL; } ix += len; BencObj *obj = BencObj::Decode(bytes + ix, &len); if (!obj) { delete key; delete dict; return NULL; } ix += len; dict->Add(key->RawValue(), obj); delete key; } if (lenOut) *lenOut = ix + 1; return dict; }
static void BencTestDictAppend() { /* test insertion in ascending order */ BencDict *dict = new BencDict(); for (size_t i = 1; i <= ITERATION_COUNT; i++) { ScopedMem<char> key(str::Format("%04u", i)); utassert(str::Len(key) == 4); dict->Add(key, i); utassert(dict->Length() == i); utassert(dict->GetInt(key)); utassert(!dict->GetString(key)); utassert(!dict->GetArray(key)); utassert(!dict->GetDict(key)); } BencInt *intObj = dict->GetInt("0123"); utassert(intObj && intObj->Value() == 123); BencTestRoundtrip(dict); delete dict; /* test insertion in descending order */ dict = new BencDict(); for (size_t i = ITERATION_COUNT; i > 0; i--) { ScopedMem<char> key(str::Format("%04u", i)); utassert(str::Len(key) == 4); BencObj *obj = new BencInt(i); dict->Add(key, obj); utassert(dict->Length() == ITERATION_COUNT + 1 - i); utassert(dict->GetInt(key)); } intObj = dict->GetInt("0123"); utassert(intObj && intObj->Value() == 123); BencTestRoundtrip(dict); delete dict; dict = new BencDict(); dict->Add("ab", 1); dict->Add("KL", 2); dict->Add("gh", 3); dict->Add("YZ", 4); dict->Add("ab", 5); BencTestSerialization(dict, "d2:KLi2e2:YZi4e2:abi5e2:ghi3ee"); delete dict->Remove("gh"); delete dict->Remove("YZ"); delete dict->Remove("missing"); BencTestSerialization(dict, "d2:KLi2e2:abi5ee"); delete dict; }
static void BencTestStress() { char key[64]; char val[64]; WCHAR tval[64]; Vec<BencObj*> stack(29); BencDict *startDict = new BencDict(); BencDict *d = startDict; BencArray *a = NULL; srand((unsigned int)time(NULL)); // generate new dict or array with 5% probability each, close an array or // dict with 8% probability (less than 10% probability of opening one, to // encourage nesting), generate int, string or raw strings uniformly // across the remaining 72% probability for (int i = 0; i < 10000; i++) { int n = rand() % 100; if (n < 5) { BencDict *nd = new BencDict(); if (a) { a->Add(nd); } else { GenRandStr(key, dimof(key)); d->Add(key, nd); } stack.Push(nd); d = nd; a = NULL; } else if (n < 10) { BencArray *na = new BencArray(); if (a) { a->Add(na); } else { GenRandStr(key, dimof(key)); d->Add(key, na); } stack.Push(na); d = NULL; a = na; } else if (n < 18) { if (stack.Count() > 0) { n = rand() % 100; stack.Pop(); BencObj *o = startDict; if (stack.Count() > 0) { o = stack.Last(); } a = NULL; d = NULL; if (BT_ARRAY == o->Type()) { a = static_cast<BencArray *>(o); } else { d = static_cast<BencDict *>(o); } } } else if (n < (18 + 24)) { int64_t v = rand(); if (a) { a->Add(v); } else { GenRandStr(key, dimof(key)); d->Add(key, v); } } else if (n < (18 + 24 + 24)) { GenRandStr(val, dimof(val)); if (a) { a->AddRaw((const char*)val); } else { GenRandStr(key, dimof(key)); d->AddRaw((const char*)key, val); } } else { GenRandTStr(tval, dimof(tval)); if (a) { a->Add(tval); } else { GenRandStr(key, dimof(key)); d->Add((const char*)key, (const WCHAR *)val); } } } char *s = startDict->Encode(); free(s); delete startDict; }
static BencDict *DisplayState_Serialize(DisplayState *ds, bool globalPrefsOnly) { BencDict *prefs = new BencDict(); if (!prefs) return NULL; prefs->Add(FILE_STR, ds->filePath); if (ds->decryptionKey) prefs->AddRaw(DECRYPTION_KEY_STR, ds->decryptionKey); prefs->Add(OPEN_COUNT_STR, ds->openCount); prefs->Add(IS_PINNED_STR, ds->isPinned); if (globalPrefsOnly || ds->useGlobalValues) { prefs->Add(USE_GLOBAL_VALUES_STR, TRUE); return prefs; } const WCHAR *mode = DisplayModeConv::NameFromEnum(ds->displayMode); prefs->Add(DISPLAY_MODE_STR, mode); prefs->Add(PAGE_NO_STR, ds->pageNo); prefs->Add(REPARSE_IDX_STR, ds->reparseIdx); prefs->Add(ROTATION_STR, ds->rotation); prefs->Add(SCROLL_X_STR, ds->scrollPos.x); prefs->Add(SCROLL_Y_STR, ds->scrollPos.y); prefs->Add(WINDOW_STATE_STR, ds->windowState); prefs->Add(WINDOW_X_STR, ds->windowPos.x); prefs->Add(WINDOW_Y_STR, ds->windowPos.y); prefs->Add(WINDOW_DX_STR, ds->windowPos.dx); prefs->Add(WINDOW_DY_STR, ds->windowPos.dy); prefs->Add(TOC_VISIBLE_STR, ds->tocVisible); prefs->Add(SIDEBAR_DX_STR, ds->sidebarDx); // BUG: 2140 if (!IsValidZoom(ds->zoomVirtual)) { CrashLogFmt("Invalid ds->zoomVirtual: %.4f\n", ds->zoomVirtual); const WCHAR *ext = str::FindCharLast(ds->filePath, L'.'); if (ext) { ScopedMem<char> extA(str::conv::ToUtf8(ext)); CrashLogFmt("File type: %s\n", extA.Get()); } CrashLogFmt("DisplayMode: %d\n", ds->displayMode); CrashLogFmt("PageNo: %d\n", ds->pageNo); } CrashIf(!IsValidZoom(ds->zoomVirtual)); ScopedMem<char> zoom(str::Format("%.4f", ds->zoomVirtual)); prefs->AddRaw(ZOOM_VIRTUAL_STR, zoom); if (ds->tocState && ds->tocState->Count() > 0) { BencArray *tocState = new BencArray(); if (tocState) { for (size_t i = 0; i < ds->tocState->Count(); i++) { tocState->Add(ds->tocState->At(i)); } prefs->Add(TOC_STATE_STR, tocState); } } return prefs; }
static BencDict* SerializeGlobalPrefs(SerializableGlobalPrefs& globalPrefs) { BencDict *prefs = new BencDict(); if (!prefs) return NULL; prefs->Add(TOOLBAR_VISIBLE_STR, globalPrefs.toolbarVisible); prefs->Add(TOC_VISIBLE_STR, globalPrefs.tocVisible); prefs->Add(FAV_VISIBLE_STR, globalPrefs.favVisible); prefs->Add(SIDEBAR_DX_STR, globalPrefs.sidebarDx); prefs->Add(TOC_DY_STR, globalPrefs.tocDy); prefs->Add(PDF_ASSOCIATE_DONT_ASK_STR, globalPrefs.pdfAssociateDontAskAgain); prefs->Add(PDF_ASSOCIATE_ASSOCIATE_STR, globalPrefs.pdfAssociateShouldAssociate); prefs->Add(BG_COLOR_STR, globalPrefs.bgColor); prefs->Add(ESC_TO_EXIT_STR, globalPrefs.escToExit); prefs->Add(USE_SYS_COLORS_STR, globalPrefs.useSysColors); prefs->Add(ENABLE_AUTO_UPDATE_STR, globalPrefs.enableAutoUpdate); prefs->Add(REMEMBER_OPENED_FILES_STR, globalPrefs.rememberOpenedFiles); prefs->Add(GLOBAL_PREFS_ONLY_STR, globalPrefs.globalPrefsOnly); prefs->Add(SHOW_RECENT_FILES_STR, globalPrefs.showStartPage); const WCHAR *mode = DisplayModeConv::NameFromEnum(globalPrefs.defaultDisplayMode); prefs->Add(DISPLAY_MODE_STR, mode); CrashIf(!IsValidZoom(globalPrefs.defaultZoom)); ScopedMem<char> zoom(str::Format("%.4f", globalPrefs.defaultZoom)); prefs->AddRaw(ZOOM_VIRTUAL_STR, zoom); prefs->Add(WINDOW_STATE_STR, globalPrefs.windowState); prefs->Add(WINDOW_X_STR, globalPrefs.windowPos.x); prefs->Add(WINDOW_Y_STR, globalPrefs.windowPos.y); prefs->Add(WINDOW_DX_STR, globalPrefs.windowPos.dx); prefs->Add(WINDOW_DY_STR, globalPrefs.windowPos.dy); if (globalPrefs.inverseSearchCmdLine) prefs->Add(INVERSE_SEARCH_COMMANDLINE, globalPrefs.inverseSearchCmdLine); prefs->Add(ENABLE_TEX_ENHANCEMENTS_STR, globalPrefs.enableTeXEnhancements); if (globalPrefs.versionToSkip) prefs->Add(VERSION_TO_SKIP_STR, globalPrefs.versionToSkip); if (globalPrefs.lastUpdateTime) prefs->AddRaw(LAST_UPDATE_STR, globalPrefs.lastUpdateTime); prefs->AddRaw(UI_LANGUAGE_STR, globalPrefs.currentLanguage); if (!globalPrefs.openCountWeek) globalPrefs.openCountWeek = GetWeekCount(); prefs->Add(OPEN_COUNT_WEEK_STR, globalPrefs.openCountWeek); prefs->Add(FWDSEARCH_OFFSET, globalPrefs.fwdSearch.offset); prefs->Add(FWDSEARCH_COLOR, globalPrefs.fwdSearch.color); prefs->Add(FWDSEARCH_WIDTH, globalPrefs.fwdSearch.width); prefs->Add(FWDSEARCH_PERMANENT, globalPrefs.fwdSearch.permanent); prefs->Add(CBX_RIGHT2LEFT, globalPrefs.cbxR2L); return prefs; }