#include "BookmarkFile.h" #include #include #include #include #include "BookmarkUtil.h" bool BookmarkFile::load(const std::string& bookPath, std::vector& bookmarks) { bookmarks.clear(); // Read/write go through PersistableStoreBase so the JSON parser and // serializer stay instantiated once, in PersistableStore.cpp. const std::string path = BookmarkUtil::getBookmarkPath(bookPath); JsonDocument doc; if (!PersistableStoreBase::readDocFromFile(path.c_str(), doc)) { return false; } JsonArray arr = doc["bookmarks"].as(); bookmarks.reserve(arr.size()); for (JsonObject obj : arr) { bookmarks.emplace_back(); auto& bookmark = bookmarks.back(); bookmark.xpath = obj["xpath"] | ""; bookmark.percentage = obj["percentage"] | static_cast(0); bookmark.summary = obj["summary"] | ""; bookmark.name = obj["name"] | ""; if (bookmark.name.size() > BookmarkEntry::MAX_NAME_LENGTH) { bookmark.name.resize(BookmarkEntry::MAX_NAME_LENGTH); } bookmark.computedSpineIndex = obj["si"] | static_cast(0); bookmark.computedChapterPageCount = obj["pc"] | static_cast(0); bookmark.computedChapterProgress = obj["pp"] | static_cast(0); if (!obj["vo"].isNull()) { bookmark.visibleTextOffset = obj["vo"] | static_cast(0); bookmark.hasVisibleTextOffset = true; } } LOG_DBG("BKM", "Loaded %zu bookmarks from file", bookmarks.size()); return true; } bool BookmarkFile::save(const std::string& bookPath, const std::vector& bookmarks) { for (const auto& bookmark : bookmarks) { if (bookmark.name.size() > BookmarkEntry::MAX_NAME_LENGTH) { LOG_ERR("BKM", "Bookmark name exceeds %zu bytes", BookmarkEntry::MAX_NAME_LENGTH); return false; } } JsonDocument doc; JsonArray arr = doc["bookmarks"].to(); LOG_DBG("BKM", "Saving %zu bookmarks to file", bookmarks.size()); for (const auto& bookmark : bookmarks) { JsonObject obj = arr.add(); obj["xpath"] = bookmark.xpath; obj["percentage"] = bookmark.percentage; obj["summary"] = bookmark.summary; if (!bookmark.name.empty()) { obj["name"] = bookmark.name; } obj["si"] = bookmark.computedSpineIndex; obj["pc"] = bookmark.computedChapterPageCount; obj["pp"] = bookmark.computedChapterProgress; if (bookmark.hasVisibleTextOffset) { obj["vo"] = bookmark.visibleTextOffset; } } // writeDocToFile ensures /.crosspoint; the bookmarks subdirectory is ours. Storage.mkdir(BookmarkUtil::getBookmarksDir().c_str()); const std::string path = BookmarkUtil::getBookmarkPath(bookPath); return PersistableStoreBase::writeDocToFile(path.c_str(), doc); }