Finetuning 2
This commit is contained in:
@@ -584,23 +584,21 @@ std::optional<uint16_t> Section::getPageForParagraphIndex(const uint16_t pIndex)
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the page that contains the requested paragraph index.
|
// Each LUT entry stores the paragraph index at page-break time — i.e. the last
|
||||||
// Each entry stores the first paragraph index for that page, so the page
|
// <p> whose start tag had been seen while page i was being laid out. Paragraph
|
||||||
// containing pIndex is the last page whose start paragraph is <= pIndex.
|
// P therefore first appears on the smallest i where storedPIdx[i] >= P.
|
||||||
uint16_t resultPage = 0;
|
|
||||||
for (uint16_t i = 0; i < count; i++) {
|
for (uint16_t i = 0; i < count; i++) {
|
||||||
uint32_t byteOffset;
|
f.seek(paragraphLutOffset + sizeof(uint16_t) + i * ENTRY_SIZE + sizeof(uint32_t));
|
||||||
uint16_t pagePIdx;
|
uint16_t pagePIdx;
|
||||||
serialization::readPod(f, byteOffset);
|
|
||||||
serialization::readPod(f, pagePIdx);
|
serialization::readPod(f, pagePIdx);
|
||||||
if (pagePIdx > pIndex) {
|
if (pagePIdx >= pIndex) {
|
||||||
break;
|
f.close();
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
resultPage = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
return resultPage;
|
return static_cast<uint16_t>(count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<uint16_t> Section::getParagraphIndexForPage(const uint16_t page) const {
|
std::optional<uint16_t> Section::getParagraphIndexForPage(const uint16_t page) const {
|
||||||
|
|||||||
@@ -47,33 +47,43 @@ struct ReverseState : StackState {
|
|||||||
const char* bestTierName = nullptr;
|
const char* bestTierName = nullptr;
|
||||||
|
|
||||||
ReverseState(const int spineIndex, const std::string& xpath) : spineIndex(spineIndex) {
|
ReverseState(const int spineIndex, const std::string& xpath) : spineIndex(spineIndex) {
|
||||||
// Parse optional /text()[N].M suffix before normalizing for element matching.
|
// Parse optional text-node suffix before normalizing for element matching.
|
||||||
|
// KOReader emits two shapes that both land here:
|
||||||
|
// /text()[N].M — explicit 1-based text-node index + codepoint offset
|
||||||
|
// /text().M — implicit first text-node (N=1) + codepoint offset
|
||||||
std::string raw = xpath;
|
std::string raw = xpath;
|
||||||
for (char& c : raw) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
for (char& c : raw) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||||
const std::string tnPat = "/text()[";
|
const std::string tnPat = "/text()";
|
||||||
const size_t tnPos = raw.rfind(tnPat);
|
const size_t tnPos = raw.rfind(tnPat);
|
||||||
if (tnPos != std::string::npos) {
|
if (tnPos != std::string::npos) {
|
||||||
const size_t numStart = tnPos + tnPat.size();
|
size_t cursor = tnPos + tnPat.size();
|
||||||
size_t numEnd = numStart;
|
int nodeIdx = 1;
|
||||||
while (numEnd < raw.size() && std::isdigit(static_cast<unsigned char>(raw[numEnd]))) {
|
bool valid = true;
|
||||||
numEnd++;
|
if (cursor < raw.size() && raw[cursor] == '[') {
|
||||||
|
cursor++;
|
||||||
|
size_t numEnd = cursor;
|
||||||
|
while (numEnd < raw.size() && std::isdigit(static_cast<unsigned char>(raw[numEnd]))) {
|
||||||
|
numEnd++;
|
||||||
|
}
|
||||||
|
if (numEnd > cursor && numEnd < raw.size() && raw[numEnd] == ']') {
|
||||||
|
nodeIdx = static_cast<int>(std::strtol(raw.substr(cursor, numEnd - cursor).c_str(), nullptr, 10));
|
||||||
|
cursor = numEnd + 1;
|
||||||
|
} else {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (numEnd > numStart && numEnd < raw.size() && raw[numEnd] == ']') {
|
if (valid && nodeIdx >= 1) {
|
||||||
const long nodeIdx = std::strtol(raw.substr(numStart, numEnd - numStart).c_str(), nullptr, 10);
|
targetTextNodeIndex = nodeIdx;
|
||||||
if (nodeIdx >= 1) {
|
if (cursor < raw.size() && raw[cursor] == '.') {
|
||||||
targetTextNodeIndex = static_cast<int>(nodeIdx);
|
cursor++;
|
||||||
size_t after = numEnd + 1;
|
size_t charEnd = cursor;
|
||||||
if (after < raw.size() && raw[after] == '.') {
|
while (charEnd < raw.size() && std::isdigit(static_cast<unsigned char>(raw[charEnd]))) {
|
||||||
after++;
|
charEnd++;
|
||||||
size_t charEnd = after;
|
}
|
||||||
while (charEnd < raw.size() && std::isdigit(static_cast<unsigned char>(raw[charEnd]))) {
|
if (charEnd > cursor) {
|
||||||
charEnd++;
|
const long charOff = std::strtol(raw.substr(cursor, charEnd - cursor).c_str(), nullptr, 10);
|
||||||
}
|
if (charOff >= 0) {
|
||||||
if (charEnd > after) {
|
targetCharOffset = static_cast<int>(charOff);
|
||||||
const long charOff = std::strtol(raw.substr(after, charEnd - after).c_str(), nullptr, 10);
|
|
||||||
if (charOff >= 0) {
|
|
||||||
targetCharOffset = static_cast<int>(charOff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user