CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
Parsing

Modules

 Parsable interface
 

Data Structures

struct  StrPatternDecl
 

Macros

#define strPatternCreate(pat, ...)   _strPatternCreate(pat, opt_flags(__VA_ARGS__))
 
#define strPatternMatch(pat, s, ...)    _strPatternMatch(pat, s, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })
 
#define strPatternMatchAt(io_pos, pat, s, ...)    _strPatternMatchAt(io_pos, pat, s, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })
 
#define strParse(s, pat, ...)    _strParse(s, pat, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })
 
#define STR_PATTERN(name, patstr, ...)    _STR_PATTERN_DECL(name, _strpat_##name, patstr, opt_flags(__VA_ARGS__))
 
#define strPat(name)   _strPatGet(&name)
 

Typedefs

typedef struct StrPattern StrPattern
 
typedef struct StrPatternDecl StrPatternDecl
 

Enumerations

enum  STRPAT_FLAGS { STRPAT_ExactWS = 0x01 , STRPAT_CaseI = 0x02 }
 Flags controlling how a pattern is compiled and matched. More...
 

Functions

void strPatternDestroy (StrPattern **pat)
 

Detailed Description

Reads structured text by matching it against a pattern written in the same style as a strFormat template. Where strFormat turns values into text, this turns text back into values.

string method = 0, target = 0;
uint8 minor = 0;
strParse(line, _SL("${string:m} ${string:t} HTTP/1.${uint:v}"),
stvpk(m, string, &method),
stvpk(t, string, &target),
stvpk(v, uint8, &minor));
#define _SL(s)
Inline ASCII string literal with compile-time embedded length (STR_LEN8). Content must be < 200 bytes...
Definition strliteral.h:207
#define strParse(s, pat,...)
Definition parse.h:309
#define stvpk(key, typen, pval)
Definition stvar.h:336

For anything a pattern cannot express - a grammar with counted repetition, or one that needs a decision made in C partway through - use the strscan cursor instead.

Pattern syntax

A pattern is literal text with three things mixed in:

A backtick escapes the character after it, which is how a pattern matches a literal $, (, ), | or backtick: `$, `(, `), `|, ``.

Whitespace in the literal text matches a run of one or more whitespace bytes, so a single space in the pattern also matches a tab or several spaces. STRPAT_ExactWS turns that off and makes whitespace match exactly as written.

Placeholders

${type[:key][(parseopts)][;default]}

type says what kind of text to match, and is one of:

The type controls matching only. What the value is finally converted into is decided by the destination it is bound to, so ${uint:port} can fill a uint16, an int64 or a string without the pattern changing.

Binding

Destinations are passed with stvp() and stvpk(), and are matched to placeholders two different ways:

The two modes are disjoint, exactly as in strFormat: a keyed placeholder never takes an unkeyed destination, and adding a keyed destination to a call cannot renumber the positional ones.

A key may appear on more than one placeholder when the pattern makes them alternatives of each other; see Optional text and alternatives. One destination then serves all of them.

A key named in the pattern with nothing bound to it is fine and is simply not written - which lets one shared pattern serve callers who want different fields out of it. The reverse is an error: a destination whose key does not appear in the pattern fails the match rather than being quietly ignored, because that is a typo, not a choice.

A placeholder that did not take part in the match leaves its destination untouched, so pre-setting it is how a call-site default is written:

uint16 port = 443; // stays 443 if the text has no port
strPatternMatch(strPat(kUrl), url, stvpk(port, uint16, &port));
#define strPatternMatch(pat, s,...)
Definition parse.h:264
#define strPat(name)
Definition parse.h:366

Optional text and alternatives

(...) groups elements together. A ? after the closing paren makes the whole group optional, and | inside it offers alternatives:

"${string:host}(:${uint:port})?" // port may be absent
"(${uint:day} ${string:mon}|${string:mon} ${uint:day}) ${uint:year}" // either order

A placeholder inside a group must be keyed. Positional order stops being meaningful once a field might not appear at all, so an unkeyed placeholder inside a group is a compile error. A skip placeholder is the exception, since it binds nowhere anyway.

Alternatives of the same group may reuse a key, as day and mon do above. Only one alternative can match, so only one of them can produce a value, and a single destination collects it whichever form the text turned out to be in. Repeating a key anywhere the two could match together - twice in one alternative, or inside a group and again outside it - is still a compile error.

A group can carry a key of its own, written after the closing paren and the optional ?. What the destination receives depends on its type:

"${string:host}(:${uint:port})?:hasport" // bool hasport
"(${uint:day} ${string:mon}|${string:mon} ${uint:day}):form" // uint8 form: 1 or 2

This is how an absent optional field is told apart from one the caller pre-filled, since a placeholder that did not participate leaves its destination alone.

A group that has no placeholder, no |, no ? and no key cannot affect anything, so it is rejected at compile time. That is deliberate: it turns a pattern containing a literal "(none)" into an error telling the author to write "`(none`)" instead of quietly matching none without the parentheses.

Defaults

;default covers the case where a field's own text is missing but the literals around it are still there:

"a=${uint:x;0},b=${uint:y}" // matches "a=,b=5" with x = 0

If the field does not match, nothing is consumed, the default text is converted into the destination, and matching carries on from the same place - the surrounding literals still have to match. For a string placeholder, "does not match" means the text came out empty.

Groups cover the other case, where the field and its surrounding text are missing. The two do not mix: **;default inside a group is a compile error.** A group already says the contents are optional, and a placeholder that could quietly succeed on nothing would make a branch always match, which would leave later alternatives unreachable for reasons no reader could see in the pattern.

The default text is checked against the placeholder's type when the pattern is compiled, so ${uint:port;https} fails to compile rather than failing on some later call.

Parse options

(parseopts) is a comma-separated list. Any type accepts:

int and uint accept:

float accepts:

string accepts:

Numbers are matched strictly by default: no leading whitespace, and no 0x prefix unless hex was asked for. This is the deliberate opposite of strToInt32()'s default, because a parser that quietly accepts a differently-spelled number is a parser two implementations can disagree about.

All or nothing

Matching happens in two passes. The first records only where each field was found; destinations are written afterwards, once the whole pattern has matched. So a failed match writes nothing at all, mirroring strFormat's "a failed format produces no output", and backtracking never has to un-write a value.

Reuse and threads

A compiled pattern is immutable, and matching writes only to the caller's own state, so one pattern can be matched from any number of threads at once. Compile once and keep it - STR_PATTERN does that for a file-scope pattern, and strParse() is the throwaway form for a pattern used once.

Macro Definition Documentation

◆ STR_PATTERN

#define STR_PATTERN (   name,
  patstr,
  ... 
)     _STR_PATTERN_DECL(name, _strpat_##name, patstr, opt_flags(__VA_ARGS__))

STR_PATTERN(name, "pattern", [flags])

Declares a file-scope pattern that compiles itself the first time it is used.

This is the form for a pattern on a hot path: the compile happens once, on the first match, and every later match reuses it. The compiled pattern is reachable from a global root for the life of the process, so it is not a leak and there is nothing to tear down.

Parameters
nameName for the declaration, passed to strPat() at the match site
patstrPattern text as a string literal
...(flags) Optional: STRPAT_FLAGS

Example:

STR_PATTERN(kReqLine, "${string:m} ${string:t} HTTP/1.${uint:v}");
strPatternMatch(strPat(kReqLine), line,
stvpk(m, string, &method),
stvpk(t, string, &target),
stvpk(v, uint8, &minor));
#define STR_PATTERN(name, patstr,...)
Definition parse.h:356

Definition at line 356 of file parse.h.

◆ strParse

#define strParse (   s,
  pat,
  ... 
)     _strParse(s, pat, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })

bool strParse(strref s, strref pat, ...)

Compiles a pattern, matches it once, and throws it away.

The convenient form for a one-off parse. Do not put it in a loop - compile the pattern with STR_PATTERN or strPatternCreate() and match that instead.

Parameters
sString to match
patPattern text
...One or more destinations, each wrapped with stvp() or stvpk()
Returns
true if the string matched and every value was stored

Example:

uint32 maj = 0, min = 0;
strParse(ver, _SL("${uint:maj}.${uint:min}"),
stvpk(maj, uint32, &maj), stvpk(min, uint32, &min));

Definition at line 309 of file parse.h.

◆ strPat

#define strPat (   name)    _strPatGet(&name)

StrPattern *strPat(name)

Returns the compiled pattern for a STR_PATTERN declaration, compiling it if this is the first use.

Parameters
nameName given to STR_PATTERN
Returns
Compiled pattern, or NULL if the pattern text is not valid

Definition at line 366 of file parse.h.

◆ strPatternCreate

#define strPatternCreate (   pat,
  ... 
)    _strPatternCreate(pat, opt_flags(__VA_ARGS__))

StrPattern *strPatternCreate(strref pat, [flags])

Compiles a pattern.

Parameters
patPattern text
...(flags) Optional: STRPAT_FLAGS
Returns
Compiled pattern, or NULL if the pattern is not valid (cxerr is set)

Example:

StrPattern *p = strPatternCreate(_SL("${uint:x},${uint:y}"));
...
strPatternDestroy(&p);
struct StrPattern StrPattern
Definition parse.h:219
#define strPatternCreate(pat,...)
Definition parse.h:238

Definition at line 238 of file parse.h.

◆ strPatternMatch

#define strPatternMatch (   pat,
  s,
  ... 
)     _strPatternMatch(pat, s, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })

bool strPatternMatch(StrPattern *pat, strref s, ...)

Matches a compiled pattern against a string and fills in the destinations.

The whole string must match. Nothing is written unless it does.

Parameters
patCompiled pattern
sString to match
...One or more destinations, each wrapped with stvp() or stvpk()
Returns
true if the string matched and every value was stored

Example:

uint32 x = 0, y = 0;
strPatternMatch(p, _SL("10,20"), stvpk(x, uint32, &x), stvpk(y, uint32, &y));

Definition at line 264 of file parse.h.

◆ strPatternMatchAt

#define strPatternMatchAt (   io_pos,
  pat,
  s,
  ... 
)     _strPatternMatchAt(io_pos, pat, s, count_macro_args(__VA_ARGS__), (stvp[]) { __VA_ARGS__ })

bool strPatternMatchAt(int32 *io_pos, StrPattern *pat, strref s, ...)

Matches a pattern against part of a string, starting where *io_pos says.

Unlike strPatternMatch(), the rest of the string after the pattern is left alone, so this is the form to use when walking through text a piece at a time. On success *io_pos moves to just past what matched; on failure it moves to where the match went wrong, which makes it an error position for free.

Parameters
io_posByte offset to start at, updated on return
patCompiled pattern
sString to match
...One or more destinations, each wrapped with stvp() or stvpk()
Returns
true if the pattern matched and every value was stored

Definition at line 285 of file parse.h.

Typedef Documentation

◆ StrPattern

typedef struct StrPattern StrPattern

A compiled pattern.

Immutable once compiled, and safe to match from several threads at once.

Definition at line 219 of file parse.h.

◆ StrPatternDecl

File-scope pattern declaration, compiled on first use.

Declared by STR_PATTERN and read with strPat(); there is no reason to build one by hand.

Enumeration Type Documentation

◆ STRPAT_FLAGS

Flags controlling how a pattern is compiled and matched.

Enumerator
STRPAT_ExactWS 

Whitespace in the pattern matches exactly, not a run.

STRPAT_CaseI 

Literal text matches without regard to case.

Definition at line 211 of file parse.h.

Function Documentation

◆ strPatternDestroy()

void strPatternDestroy ( StrPattern **  pat)

Releases a compiled pattern.

Parameters
patPointer to the pattern handle, which is set to NULL