File-Raw-XML
view release on metacpan or search on metacpan
include/frx_abi.h view on Meta::CPAN
* table; everything a version 1 consumer resolved is where it was.
*
* Perl headers (EXTERN.h / perl.h / XSUB.h) must be included before this
* file so SV, STRLEN and pTHX are defined. Only the entries that touch an
* SV take pTHX_; the tree accessors are plain C, callable from a harness
* with no interpreter.
*
* Three departures from the design in Punk/plan/punk-saml/01-file-raw-xml.md:
*
* - frx_c14n.mode replaces `int exclusive`: three algorithms ship
* (Exclusive 1.0, Canonical XML 1.0, Canonical XML 1.1).
* - FRX_DOCUMENT is a node kind: a signature whose Reference has URI=""
* is over the whole document, and canonicalising it means an apex that
* is the document node, with top-level comments and processing
* instructions rendered under the document-level newline rules. The
* document node's children are the top-level misc and the root
* element; root() still returns the root element; parent() of the root
* is the document node.
* - document() is appended after root().
*
* Ownership: every string the table returns is borrowed from the document,
* NUL-terminated, and valid until doc_free. Every node is borrowed from its
* document: a consumer that holds a node holds the document. Every SV the
* table returns has a reference count of one owned by the caller.
*
* One entry departs from that, and only one: `doc_to_sv` takes ownership of
* the document it is given, because the point of it is to put the document
* under the blessed SV's magic. It is called out again where it is
* declared.
*
* Two lifetimes are shorter than that, and both are the reader's. A
* string from `reader_str` or `reader_attr` lives in the arena the reader
* releases at the end of each record, so it is valid until the next
* `reader_next` and not after; copy it if you need it longer. The
* `frx_err *` from `reader_error` is valid while the reader is.
*
* A message never is. `frx_err.what` is a static string and so is the
* compile refusal from `xpath_compile`, precisely so that a consumer can
* free what failed and then report it: a message built from arena memory
* and read after the free is a use-after-free whose only symptom is a
* wrong message, which is the hardest kind to notice. */
#define FRX_ABI_VERSION 2
typedef struct frx_doc frx_doc; /* opaque; owns every node and string */
typedef struct frx_node frx_node; /* opaque; borrowed from its doc */
/* ---- refusals -----------------------------------------------------------
*
* The core never croaks: it fills an frx_err and returns NULL or 0. The
* `parse` entry renders that into a mortal SV, because it is the entry a
* consumer reaches for first and a message is what it wants; every other
* entry that can fail takes an frx_err * and the consumer renders it with
* `err_format`, so no entry needs a wrapper to translate one. */
typedef enum {
FRX_OK = 0,
FRX_E_NOMEM, /* an allocation failed */
FRX_E_TOO_LARGE, /* over max_bytes */
FRX_E_TOO_DEEP, /* over max_depth */
FRX_E_ENCODING, /* not UTF-8: a BOM, a declaration, a first pair */
FRX_E_DOCTYPE, /* <!DOCTYPE, or any <! that is not -- or [CDATA[ */
FRX_E_UTF8, /* a byte sequence that is not UTF-8, or not Char */
FRX_E_SYNTAX, /* not well-formed */
FRX_E_NAME, /* not a Name, or a QName with the wrong colons */
FRX_E_REFERENCE, /* an undeclared entity, or a reference to a non-Char */
FRX_E_NAMESPACE, /* unbound prefix, xmlns misuse, a relative URI */
FRX_E_DUP_ATTR, /* the same attribute twice, literally or expanded */
FRX_E_DUP_ID, /* two elements with one ID value */
FRX_E_ROOT, /* no root element, or more than one */
FRX_E_DTD, /* full: a markup declaration that is not well-formed */
FRX_E_ENTITY, /* full: an entity well-formedness constraint */
FRX_E_EXPANSION, /* full: an entity expansion budget crossed */
FRX_E_VALIDITY /* full: a validity constraint, under validate */
} frx_code;
typedef struct frx_err {
frx_code code;
size_t offset;
const char *what; /* static; never arena memory */
const char *enc; /* the input's encoding when it was transcoded and
* offset indexes the caller's bytes; NULL otherwise */
} frx_err;
/* node kinds; CDATA is text in the data model and merges into it at parse */
enum { FRX_ELEMENT = 1, FRX_TEXT, FRX_COMMENT, FRX_PI, FRX_DOCUMENT };
/* canonicalisation algorithms */
enum { FRX_C14N_EXC = 0, FRX_C14N_INC10, FRX_C14N_INC11 };
/* Parse options. Fill with opts_init() (or pass NULL to parse) for the
* defaults, then set what you need. */
typedef struct frx_opts {
size_t max_bytes; /* 0: no cap */
int max_depth; /* 0: the default, 256 */
const char *const *id_attrs; /* attribute local names that are IDs,
* in any namespace; NULL: no index */
int n_id_attrs;
} frx_opts;
/* Canonicalisation options. */
typedef struct frx_c14n {
int mode; /* FRX_C14N_* */
int comments; /* 1: render comments */
const char *const *prefix_list; /* InclusiveNamespaces PrefixList;
* "#default" names the default ns */
int n_prefix;
const frx_node *const *without; /* subtrees omitted from the node set:
* the enveloped-signature transform */
int n_without;
} frx_c14n;
/* ---- the full profile's options ------------------------------------------
*
* frx_opts is in the table by pointer with no size field, so once this
* ships it can never grow: a later provider would read past an older
* consumer's struct. frx_opts_ex is the struct the full profile grows
* into instead. It begins with `size`, the sizeof the consumer was
* compiled with, and every reader copies min(size, its own sizeof) over a
* defaults block, so a later version can append fields and an older
* consumer's shorter struct is still read whole. A field that turns out
( run in 1.193 second using v1.01-cache-2.11-cpan-8dfa8b56332 )