#GFM Markdown Parser
#define FIO_GFM
#include "fio-stl.h"A flat-state, non-recursive parser for GitHub Flavored Markdown. It emits block and inline events through three callbacks — push, write, pop — without allocating heap memory itself. fio_gfm_parse is the only public entry point.
The parser depends on FIO_ENTITY for HTML entity decoding.
#Configuration Macros
#FIO_GFM_MAX_DEPTH
#define FIO_GFM_MAX_DEPTH 255Maximum container nesting depth. Must fit in a byte (≤ 255).
#FIO_GFM_MAX_TABLE_COLUMNS
#define FIO_GFM_MAX_TABLE_COLUMNS 64Maximum table columns. Alignment is bit-packed, so four columns fit in one byte.
#FIO_GFM_REF_CACHE_SIZE
#define FIO_GFM_REF_CACHE_SIZE 128Maximum reference definitions held in the fast inline cache.
#Error Codes
#FIO_GFM_ERR_GENERIC, FIO_GFM_ERR_DEPTH, FIO_GFM_ERR_INPUT
#define FIO_GFM_ERR_GENERIC -1
#define FIO_GFM_ERR_DEPTH -2
#define FIO_GFM_ERR_INPUT -3Negative error codes used internally and returned through fio_gfm_parse.
#Flags
#FIO_GFM_F_TIGHT
#define FIO_GFM_F_TIGHT ((uint8_t)1U << 0)The list is tight (no blank lines between items).
#FIO_GFM_F_LOOSE_SEEN
#define FIO_GFM_F_LOOSE_SEEN ((uint8_t)1U << 1)A blank line was seen between list items.
#FIO_GFM_F_TASK
#define FIO_GFM_F_TASK ((uint8_t)1U << 2)The list item is a task-list item.
#FIO_GFM_F_TASK_CHECKED
#define FIO_GFM_F_TASK_CHECKED ((uint8_t)1U << 3)The task-list marker is checked ([x]).
#Types
#fio_gfm_type_e
typedef enum {
FIO_GFM_PARAGRAPH = 1,
FIO_GFM_HEADING,
FIO_GFM_THEMATIC_BREAK,
FIO_GFM_BLOCKQUOTE,
FIO_GFM_LIST_UNORDERED,
FIO_GFM_LIST_ORDERED,
FIO_GFM_LIST_ITEM,
FIO_GFM_CODE_BLOCK,
FIO_GFM_HTML_BLOCK,
FIO_GFM_TABLE,
FIO_GFM_TABLE_ROW,
FIO_GFM_TABLE_CELL,
FIO_GFM_EMPHASIS,
FIO_GFM_STRONG,
FIO_GFM_STRIKETHROUGH,
FIO_GFM_LINK,
FIO_GFM_TEXT,
FIO_GFM_SOFT_BREAK,
FIO_GFM_HARD_BREAK,
FIO_GFM_CODE_SPAN,
FIO_GFM_IMAGE,
FIO_GFM_AUTOLINK,
FIO_GFM_INLINE_HTML,
FIO_GFM_FOOTNOTE_REF,
} fio_gfm_type_e;Event type. Values 1–12 are block sections; 13–16 are inline sections; 17–23 are text and leaf content emitted with write.
#fio_gfm_align_e
typedef enum {
FIO_GFM_ALIGN_NONE = 0,
FIO_GFM_ALIGN_LEFT,
FIO_GFM_ALIGN_RIGHT,
FIO_GFM_ALIGN_CENTER,
} fio_gfm_align_e;Table cell alignment.
#fio_gfm_event_s
typedef struct {
void *udata;
fio_buf_info_s source;
fio_buf_info_s text;
fio_buf_info_s marker;
fio_buf_info_s info;
fio_buf_info_s destination;
fio_buf_info_s title;
fio_buf_info_s reference;
uint32_t list_start;
uint16_t columns;
uint16_t column;
uint8_t type;
uint8_t heading_level;
uint8_t flags;
uint8_t align;
uint8_t padding;
} fio_gfm_event_s;Event passed to every callback.
Fields:
udata— live user pointer; the parser copies it back after each callback.source— full source slice for this event.text— literal text / label / code content.marker— marker slice (#, fence, list bullet, etc.).info— fenced code info string (language tag).destination— link/image/autolink URL.title— link/image title.reference— reference label for ref-style links/images.list_start— ordered list start number.columns/column— table column count and cell index.type—fio_gfm_type_evalue.heading_level—1–6for headings.flags—FIO_GFM_F_*.align—fio_gfm_align_efor table cells.padding— virtual leading spaces from tab expansion.
#fio_gfm_callbacks_s
typedef struct {
int (*push)(fio_gfm_event_s *e);
int (*write)(fio_gfm_event_s *e);
int (*pop)(fio_gfm_event_s *e);
} fio_gfm_callbacks_s;Parser callbacks. All are optional. Return 0 to continue, non-zero to abort. Positive values are user errors; negative values are reserved for parser errors.
#Parsing
#fio_gfm_parse
SFUNC size_t fio_gfm_parse(const fio_gfm_callbacks_s *callbacks,
void *udata,
fio_buf_info_s source);Parses a complete Markdown document and emits events. The document must be fully available in source; streaming is not supported.
Parameters:
callbacks— pointer to callback struct.udata— user pointer copied into every event; callbacks may update it.source— full document bytes.
Returns: the number of bytes consumed. If this equals source.len, parsing completed. A smaller value means a callback aborted or a parser error occurred.
#Example
#define FIO_GFM
#include "fio-stl.h"
static int on_push(fio_gfm_event_s *e) {
fprintf(stderr, "open type=%u\n", e->type);
return 0;
}
static int on_write(fio_gfm_event_s *e) {
fprintf(stderr, "text: %.*s\n", (int)e->text.len, e->text.buf);
return 0;
}
static int on_pop(fio_gfm_event_s *e) {
fprintf(stderr, "close type=%u\n", e->type);
return 0;
}
int main(void) {
fio_gfm_callbacks_s cb = {
.push = on_push,
.write = on_write,
.pop = on_pop,
};
fio_buf_info_s src = FIO_BUF_INFO2("# Hello\n\nworld.\n", 16);
size_t n = fio_gfm_parse(&cb, NULL, src);
fprintf(stderr, "consumed %zu of %zu bytes\n", n, src.len);
return 0;
}