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

Modules

 Literals and Characters
 
 Extraction
 
 Typed Values
 

Data Structures

struct  strscan
 

Macros

#define strscInit(sc, s, ...)   _strscInit(sc, s, opt_flags(__VA_ARGS__))
 

Typedefs

typedef struct strscan strscan
 

Enumerations

enum  STRSC_FLAGS { STRSC_CaseInsensitive = 0x01 }
 Flags controlling how a scanner matches. More...
 

Functions

bool strscFinish (strscan *sc)
 
bool strscDone (strscan *sc)
 
int32 strscMark (strscan *sc)
 
void strscRewind (strscan *sc, int32 mark)
 
bool strscSeek (strscan *sc, int32 pos)
 
void strscFail (strscan *sc)
 

Detailed Description

A cursor that walks a string left to right, matching and extracting pieces as it goes. This is the low-level half of cx's parsing support: use it for grammars that a pattern cannot express, and use pattern matching for everything else.

The sticky error flag

A scanner carries an ok flag that starts true and turns false the first time something does not match. Once it is false every later call does nothing and returns false immediately. That means a grammar can be written as a straight run of calls with a single check at the end, instead of an if around every step:

strscInit(&sc, line);
string method = 0, target = 0;
uint32 minor = 0;
strscToken(&sc, &method, _SL(" "));
strscWS1(&sc);
strscToken(&sc, &target, _SL(" "));
strscWS1(&sc);
strscLit(&sc, _SL("HTTP/1."));
strscUInt32(&sc, &minor, 10);
if (!strscFinish(&sc)) {
// something above did not match; strscErrPos said where
}
#define _SL(s)
Inline ASCII string literal with compile-time embedded length (STR_LEN8). Content must be < 200 bytes...
Definition strliteral.h:207
bool strscToken(strscan *sc, string *out, strref delims)
bool strscWS1(strscan *sc)
bool strscLit(strscan *sc, strref lit)
bool strscUInt32(strscan *sc, uint32 *out, int base)
bool strscFinish(strscan *sc)
#define strscInit(sc, s,...)
Definition strscan.h:104

Backtracking

strscMark() records the current position and strscRewind() returns to it. Rewinding also clears the error flag, so it is how alternatives are tried:

int32 mark = strscMark(&sc);
if (!parseFirstForm(&sc)) {
strscRewind(&sc, mark);
parseSecondForm(&sc);
}
int32 strscMark(strscan *sc)
Definition strscan.h:136
void strscRewind(strscan *sc, int32 mark)

Lifetime

The scanner borrows the string rather than holding a reference to it, so the string must stay alive for as long as the scanner is in use. Extracted pieces are ordinary strings that the caller owns and must destroy.

Macro Definition Documentation

◆ strscInit

#define strscInit (   sc,
  s,
  ... 
)    _strscInit(sc, s, opt_flags(__VA_ARGS__))

void strscInit(strscan *sc, strref s, [flags])

Starts a scan at the beginning of a string.

The string is borrowed, so it must outlive the scanner.

Parameters
scScanner to initialize
sString to scan (NULL scans an empty string)
...(flags) Optional: STRSC_FLAGS

Example:

strscInit(&sc, line);
@ STRSC_CaseInsensitive
Literals and character sets match without regard to case.
Definition strscan.h:65

Definition at line 104 of file strscan.h.

Typedef Documentation

◆ strscan

typedef struct strscan strscan

String scanner state

Read pos, errpos, ok and s freely; change the position with strscSeek() or strscRewind() rather than by assignment.

Enumeration Type Documentation

◆ STRSC_FLAGS

Flags controlling how a scanner matches.

Enumerator
STRSC_CaseInsensitive 

Literals and character sets match without regard to case.

Definition at line 64 of file strscan.h.

Function Documentation

◆ strscDone()

bool strscDone ( strscan sc)
inline

bool strscDone(strscan *sc)

Tests whether the cursor has reached the end of the string.

Parameters
scScanner to test
Returns
true if there is nothing left to read

Definition at line 124 of file strscan.h.

◆ strscFail()

void strscFail ( strscan sc)

Marks the scan as failed at the current position.

For a check the scanner itself cannot make - a day number that parsed fine but is out of range, say. Does nothing if the scan has already failed.

Parameters
scScanner to fail

◆ strscFinish()

bool strscFinish ( strscan sc)

Ends a scan and reports whether everything matched.

Does not check that the whole string was consumed - call strscDone() before this if the grammar requires that.

The scanner lets go of the string here, so nothing may be matched or extracted afterward; ok and errpos are still set, which is what an error report needs.

Parameters
scScanner to finish
Returns
true if no step failed

◆ strscMark()

int32 strscMark ( strscan sc)
inline

int32 strscMark(strscan *sc)

Records the current position so strscRewind() can come back to it. Currently is the same as reading pos, but this may change so do not depend on it.

Parameters
scScanner to inspect
Returns
Opaque position marker

Definition at line 136 of file strscan.h.

◆ strscRewind()

void strscRewind ( strscan sc,
int32  mark 
)

Returns to a recorded position and clears the error flag.

This is how alternatives are tried: mark, attempt one form, and rewind to attempt another. Clearing the error is the point - a failed attempt that has been rewound never happened.

Parameters
scScanner to reposition
markPosition from strscMark()

◆ strscSeek()

bool strscSeek ( strscan sc,
int32  pos 
)

Moves the cursor to an absolute offset.

Unlike strscRewind(), this does not clear the error flag, and it fails if the offset is outside the string.

Parameters
scScanner to reposition
posByte offset to move to
Returns
true if the offset was in range