Change opds parser interface

This commit is contained in:
Konstantin Vukolov 2026-01-20 16:27:45 +03:00
parent 5cd56af350
commit c22a2b56fb
4 changed files with 27 additions and 16 deletions

View File

@ -22,9 +22,14 @@ OpdsParser::~OpdsParser() {
} }
} }
void OpdsParser::push(const char* xmlData, const size_t length) { size_t OpdsParser::write(uint8_t c) {
return write(&c, 1);
}
size_t OpdsParser::write(const uint8_t* xmlData, const size_t length) {
Serial.printf("Got %d bytes to parse\n", length);
if (errorOccured) { if (errorOccured) {
return; return length;
} }
XML_SetUserData(parser, this); XML_SetUserData(parser, this);
@ -32,7 +37,7 @@ void OpdsParser::push(const char* xmlData, const size_t length) {
XML_SetCharacterDataHandler(parser, characterData); XML_SetCharacterDataHandler(parser, characterData);
// Parse in chunks to avoid large buffer allocations // Parse in chunks to avoid large buffer allocations
const char* currentPos = xmlData; const char* currentPos = reinterpret_cast<const char*>(xmlData);
size_t remaining = length; size_t remaining = length;
constexpr size_t chunkSize = 1024; constexpr size_t chunkSize = 1024;
@ -43,7 +48,7 @@ void OpdsParser::push(const char* xmlData, const size_t length) {
Serial.printf("[%lu] [OPDS] Couldn't allocate memory for buffer\n", millis()); Serial.printf("[%lu] [OPDS] Couldn't allocate memory for buffer\n", millis());
XML_ParserFree(parser); XML_ParserFree(parser);
parser = nullptr; parser = nullptr;
return; return length;
} }
const size_t toRead = remaining < chunkSize ? remaining : chunkSize; const size_t toRead = remaining < chunkSize ? remaining : chunkSize;
@ -55,7 +60,7 @@ void OpdsParser::push(const char* xmlData, const size_t length) {
XML_ErrorString(XML_GetErrorCode(parser))); XML_ErrorString(XML_GetErrorCode(parser)));
XML_ParserFree(parser); XML_ParserFree(parser);
parser = nullptr; parser = nullptr;
return; return length;
} }
currentPos += toRead; currentPos += toRead;
@ -63,7 +68,7 @@ void OpdsParser::push(const char* xmlData, const size_t length) {
} }
} }
void OpdsParser::finish() { void OpdsParser::flush() {
if (XML_Parse(parser, nullptr, 0, XML_TRUE) != XML_STATUS_OK) { if (XML_Parse(parser, nullptr, 0, XML_TRUE) != XML_STATUS_OK) {
errorOccured = true; errorOccured = true;
XML_ParserFree(parser); XML_ParserFree(parser);

View File

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "Print.h"
/** /**
* Type of OPDS entry. * Type of OPDS entry.
@ -42,7 +43,7 @@ using OpdsBook = OpdsEntry;
* } * }
* } * }
*/ */
class OpdsParser { class OpdsParser final : public Print {
public: public:
OpdsParser(); OpdsParser();
~OpdsParser(); ~OpdsParser();
@ -51,10 +52,17 @@ class OpdsParser {
OpdsParser(const OpdsParser&) = delete; OpdsParser(const OpdsParser&) = delete;
OpdsParser& operator=(const OpdsParser&) = delete; OpdsParser& operator=(const OpdsParser&) = delete;
void push(const char* xmlData, size_t length); size_t write(uint8_t) override;
void finish(); size_t write(const uint8_t*, size_t) override;
void flush() override;
bool error() const; bool error() const;
operator bool() {
return !error();
}
/** /**
* Get the parsed entries (both navigation and book entries). * Get the parsed entries (both navigation and book entries).
* @return Vector of OpdsEntry entries * @return Vector of OpdsEntry entries

View File

@ -9,13 +9,11 @@ int OpdsParserStream::peek() { abort(); }
int OpdsParserStream::read() { abort(); } int OpdsParserStream::read() { abort(); }
size_t OpdsParserStream::write(uint8_t c) { size_t OpdsParserStream::write(uint8_t c) {
parser.push(reinterpret_cast<const char*>(&c), 1); return parser.write(c);
return 1;
} }
size_t OpdsParserStream::write(const uint8_t* buffer, size_t size) { size_t OpdsParserStream::write(const uint8_t* buffer, size_t size) {
parser.push(reinterpret_cast<const char*>(buffer), size); return parser.write(buffer, size);
return size;
} }
OpdsParserStream::~OpdsParserStream() { parser.finish(); } OpdsParserStream::~OpdsParserStream() { parser.flush(); }

View File

@ -17,7 +17,7 @@
namespace { namespace {
constexpr int PAGE_ITEMS = 23; constexpr int PAGE_ITEMS = 23;
constexpr int SKIP_PAGE_MS = 700; constexpr int SKIP_PAGE_MS = 700;
constexpr char OPDS_ROOT_PATH[] = "opds"; // No leading slash - relative to server URL constexpr char OPDS_ROOT_PATH[] = "api/opds/c7f8522c-5539-4f60-b978-3626a33245b6"; // No leading slash - relative to server URL
} // namespace } // namespace
void OpdsBookBrowserActivity::taskTrampoline(void* param) { void OpdsBookBrowserActivity::taskTrampoline(void* param) {
@ -277,7 +277,7 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
} }
} }
if (parser.error()) { if (!parser) {
state = BrowserState::ERROR; state = BrowserState::ERROR;
errorMessage = "Failed to parse feed"; errorMessage = "Failed to parse feed";
updateRequired = true; updateRequired = true;