mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-24 03:29:58 +00:00
205 lines
6.5 KiB
C++
205 lines
6.5 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace UI::LXMF::NomadNet {
|
|
|
|
enum class BlockType { TEXT, HEADING, DIVIDER, TABLE, PARTIAL, UNSUPPORTED };
|
|
enum class Alignment { LEFT, CENTER, RIGHT };
|
|
enum class FormFieldType : uint8_t { TEXT, PASSWORD, CHECKBOX, RADIO };
|
|
enum class ParseStatus : uint8_t { OK, INVALID_INPUT, ALLOCATION_FAILED };
|
|
|
|
enum class TruncationReason : uint32_t {
|
|
NONE = 0,
|
|
DOCUMENT_BYTES = 1 << 0,
|
|
SOURCE_LINES = 1 << 1,
|
|
SOURCE_LINE_BYTES = 1 << 2,
|
|
BLOCKS = 1 << 3,
|
|
RUNS_PER_LINE = 1 << 4,
|
|
TOTAL_RUNS = 1 << 5,
|
|
LINKS = 1 << 6,
|
|
ANCHORS = 1 << 7,
|
|
ANCHOR_NAME_BYTES = 1 << 8,
|
|
TABLES = 1 << 9,
|
|
TABLE_ROWS = 1 << 10,
|
|
TABLE_COLUMNS = 1 << 11,
|
|
TABLE_CELL_BYTES = 1 << 12,
|
|
TABLE_BYTES = 1 << 13,
|
|
TABLE_CELLS = 1 << 14,
|
|
TABLE_FALLBACK_BYTES = 1u << 15,
|
|
FORM_FIELDS = 1u << 16,
|
|
FORM_NAME_BYTES = 1u << 17,
|
|
FORM_VALUE_BYTES = 1u << 18,
|
|
FORM_LABEL_BYTES = 1u << 19,
|
|
FORM_BYTES = 1u << 20,
|
|
PARTIALS = 1u << 21,
|
|
PARTIAL_DESCRIPTOR_BYTES = 1u << 22,
|
|
PARTIAL_FIELDS = 1u << 23,
|
|
PARTIAL_FIELD_BYTES = 1u << 24,
|
|
};
|
|
|
|
struct Run {
|
|
std::string text;
|
|
bool bold = false;
|
|
bool italic = false;
|
|
bool underline = false;
|
|
bool has_foreground = false;
|
|
uint32_t foreground = 0;
|
|
bool has_background = false;
|
|
uint32_t background = 0;
|
|
int link_index = -1;
|
|
int field_index = -1;
|
|
};
|
|
|
|
struct FormField {
|
|
uint16_t id = 0;
|
|
FormFieldType type = FormFieldType::TEXT;
|
|
std::string name;
|
|
std::string value;
|
|
std::string label;
|
|
uint16_t width = 24;
|
|
bool checked = false;
|
|
bool masked = false;
|
|
};
|
|
|
|
struct TableCell {
|
|
uint32_t first_run = 0;
|
|
uint16_t run_count = 0;
|
|
Alignment alignment = Alignment::LEFT;
|
|
};
|
|
|
|
struct Table {
|
|
uint32_t first_cell = 0;
|
|
uint16_t row_count = 0;
|
|
uint8_t column_count = 0;
|
|
Alignment alignment = Alignment::LEFT;
|
|
uint16_t max_width = 100;
|
|
};
|
|
|
|
struct Partial {
|
|
std::string descriptor;
|
|
std::string url;
|
|
std::string selectors;
|
|
std::string id;
|
|
std::vector<std::string> fields;
|
|
std::array<uint8_t, 32> descriptor_hash{};
|
|
uint32_t refresh_interval_ms = 0;
|
|
};
|
|
|
|
struct Block {
|
|
BlockType type = BlockType::TEXT;
|
|
uint8_t depth = 0;
|
|
Alignment alignment = Alignment::LEFT;
|
|
uint32_t divider_codepoint = 0x2500;
|
|
int16_t table_index = -1;
|
|
int16_t partial_index = -1;
|
|
int16_t partial_region_index = -1;
|
|
std::vector<Run> runs;
|
|
};
|
|
|
|
struct Link {
|
|
Link() = default;
|
|
Link(const std::string& link_label, const std::string& link_target,
|
|
const std::string& link_fields, bool contains_fields = false)
|
|
: label(link_label), target(link_target), fields(link_fields), has_fields(contains_fields) {}
|
|
|
|
std::string label;
|
|
std::string target;
|
|
std::string fields;
|
|
bool has_fields = false;
|
|
};
|
|
|
|
struct Anchor {
|
|
Anchor() = default;
|
|
Anchor(const std::string& value, uint16_t block)
|
|
: name(value), block_index(block) {}
|
|
|
|
std::string name;
|
|
uint16_t block_index = 0;
|
|
};
|
|
|
|
struct Document {
|
|
std::vector<Block> blocks;
|
|
std::vector<Link> links;
|
|
std::vector<Anchor> anchors;
|
|
std::vector<Table> tables;
|
|
std::vector<TableCell> table_cells;
|
|
std::vector<Run> table_runs;
|
|
std::vector<FormField> fields;
|
|
std::vector<Partial> partials;
|
|
uint32_t cache_seconds = 12U * 60U * 60U;
|
|
bool has_cache_directive = false;
|
|
bool cache_directive_valid = true;
|
|
bool has_background = false;
|
|
uint32_t background = 0;
|
|
bool has_foreground = false;
|
|
uint32_t foreground = 0;
|
|
bool truncated = false;
|
|
bool malformed = false;
|
|
bool unsupported = false;
|
|
bool allocation_failed = false;
|
|
std::size_t source_bytes = 0;
|
|
std::size_t source_lines = 0;
|
|
uint32_t truncation_reasons = 0;
|
|
std::size_t form_bytes = 0;
|
|
|
|
void mark_truncated(TruncationReason reason) {
|
|
truncated = true;
|
|
truncation_reasons |= static_cast<uint32_t>(reason);
|
|
}
|
|
bool has_truncation(TruncationReason reason) const {
|
|
return (truncation_reasons & static_cast<uint32_t>(reason)) != 0;
|
|
}
|
|
};
|
|
|
|
class DocumentParser {
|
|
public:
|
|
static constexpr std::size_t MAX_DOCUMENT_BYTES = 64 * 1024;
|
|
static constexpr std::size_t MAX_SOURCE_LINES = 4096;
|
|
static constexpr std::size_t MAX_BLOCKS = 1024;
|
|
static constexpr std::size_t MAX_RUNS_PER_LINE = 128;
|
|
static constexpr std::size_t MAX_TOTAL_RUNS = 1024;
|
|
static constexpr std::size_t MAX_SOURCE_LINE_BYTES = 4096;
|
|
static constexpr std::size_t MAX_LINKS = 128;
|
|
static constexpr std::size_t MAX_ANCHORS = 128;
|
|
static constexpr std::size_t MAX_ANCHOR_NAME_BYTES = 64;
|
|
static constexpr std::size_t MAX_TABLES = 16;
|
|
static constexpr std::size_t MAX_TABLE_ROWS = 32;
|
|
static constexpr std::size_t MAX_TABLE_COLUMNS = 8;
|
|
static constexpr std::size_t MAX_TABLE_CELLS = 256;
|
|
static constexpr std::size_t MAX_TOTAL_TABLE_CELLS = 512;
|
|
static constexpr std::size_t MAX_TABLE_CELL_BYTES = 512;
|
|
static constexpr std::size_t MAX_TABLE_FALLBACK_BYTES = 1024;
|
|
static constexpr std::size_t MAX_TABLE_BYTES = 16 * 1024;
|
|
static constexpr std::size_t MAX_FIELDS = 64;
|
|
static constexpr std::size_t MAX_FIELD_NAME_BYTES = 64;
|
|
static constexpr std::size_t MAX_FIELD_VALUE_BYTES = 512;
|
|
static constexpr std::size_t MAX_FIELD_LABEL_BYTES = 256;
|
|
static constexpr std::size_t MAX_FORM_BYTES = 16 * 1024;
|
|
static constexpr std::size_t MAX_PARTIALS = 16;
|
|
static constexpr std::size_t MAX_PARTIAL_DESCRIPTOR_BYTES = 1024;
|
|
static constexpr std::size_t MAX_PARTIAL_URL_BYTES = 512;
|
|
static constexpr std::size_t MAX_PARTIAL_FIELDS = 64;
|
|
static constexpr std::size_t MAX_PARTIAL_FIELD_BYTES = 511;
|
|
static constexpr std::size_t MAX_PARTIAL_ID_BYTES = 64;
|
|
static constexpr uint32_t MAX_PARTIAL_REFRESH_MS = 604800000U;
|
|
static constexpr std::size_t MAX_PARTIAL_BYTES = 8 * 1024;
|
|
static constexpr uint16_t DEFAULT_FIELD_WIDTH = 24;
|
|
static constexpr uint16_t MAX_FIELD_WIDTH = 256;
|
|
static constexpr uint16_t DEFAULT_TABLE_WIDTH = 100;
|
|
static constexpr uint16_t MAX_TABLE_WIDTH = UINT16_MAX;
|
|
static constexpr uint32_t MAX_CACHE_SECONDS = 7 * 24 * 60 * 60;
|
|
|
|
Document parse(const std::string& source) const;
|
|
Document parse(const char* source, std::size_t size) const;
|
|
ParseStatus parse_into(const char* source, std::size_t size, Document& output) const noexcept;
|
|
};
|
|
|
|
std::string truncation_notice(const Document& document);
|
|
|
|
} // namespace UI::LXMF::NomadNet
|