MCPcopy Index your code
hub / github.com/crosspoint-reader/crosspoint-reader / parseXPathSteps

Function parseXPathSteps

lib/KOReaderSync/ProgressMapper.cpp:134–184  ·  view source on GitHub ↗

Parse the XPath segment between /body/DocFragment[N]/body/ and the terminal position into an ordered sequence of steps. Returns step count, 0 on failure. Example input: "/body/DocFragment[1]/body/div[1]/ul/li[4]/text()[1].51" Fills steps with: {div,1}, {ul,1}, {li,4}

Source from the content-addressed store, hash-verified

132// Example input: "/body/DocFragment[1]/body/div[1]/ul/li[4]/text()[1].51"
133// Fills steps with: {div,1}, {ul,1}, {li,4}
134int parseXPathSteps(const std::string& xpath, XPathStep steps[MAX_XPATH_DEPTH]) {
135 static const char kBodyFrag[] = "/body/DocFragment[";
136 const size_t fragPos = xpath.find(kBodyFrag);
137 if (fragPos == std::string::npos) return 0;
138 const size_t afterBracket = xpath.find(']', fragPos + strlen(kBodyFrag));
139 if (afterBracket == std::string::npos) return 0;
140 static const char kBody[] = "/body/";
141 if (xpath.compare(afterBracket + 1, strlen(kBody), kBody) != 0) return 0;
142 size_t pos = afterBracket + 1 + strlen(kBody);
143
144 size_t stepsEnd = xpath.rfind("/text()");
145 if (stepsEnd == std::string::npos) {
146 stepsEnd = xpath.rfind('.');
147 if (stepsEnd == std::string::npos || stepsEnd <= pos || stepsEnd + 1 >= xpath.size()) return 0;
148 for (size_t i = stepsEnd + 1; i < xpath.size(); i++) {
149 if (xpath[i] < '0' || xpath[i] > '9') return 0;
150 }
151 }
152 if (stepsEnd <= pos) return 0;
153
154 int count = 0;
155 while (pos < stepsEnd && count < MAX_XPATH_DEPTH) {
156 const size_t slash = xpath.find('/', pos);
157 const size_t segEnd = (slash < stepsEnd) ? slash : stepsEnd;
158
159 XPathStep& step = steps[count];
160 const size_t bracket = xpath.find('[', pos);
161 const size_t nameEnd = (bracket != std::string::npos && bracket < segEnd) ? bracket : segEnd;
162 const size_t nameLen = nameEnd - pos;
163 if (nameLen == 0 || nameLen >= sizeof(step.tag)) return 0;
164 memcpy(step.tag, xpath.c_str() + pos, nameLen);
165 step.tag[nameLen] = '\0';
166
167 if (bracket != std::string::npos && bracket < segEnd) {
168 const size_t closeBracket = xpath.find(']', bracket + 1);
169 if (closeBracket == std::string::npos || closeBracket > segEnd) return 0;
170 int idx = 0;
171 for (size_t i = bracket + 1; i < closeBracket; i++) {
172 if (xpath[i] < '0' || xpath[i] > '9') return 0;
173 idx = idx * 10 + (xpath[i] - '0');
174 }
175 step.siblingIndex = idx;
176 } else {
177 step.siblingIndex = 1;
178 }
179
180 count++;
181 pos = (slash < stepsEnd) ? slash + 1 : stepsEnd;
182 }
183 return count;
184}
185
186class ParagraphStreamer final : public Print {
187 size_t bytesWritten = 0;

Callers 1

toCrossPointMethod · 0.85

Calls 1

sizeMethod · 0.45

Tested by

no test coverage detected