diff --git a/src/Parser.c b/src/Parser.c index 5801634..aee970b 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -24,149 +24,47 @@ #include -#include #include -#include #include -#include - -struct Parser { - char *string; - size_t idx; - - ssize_t mark; - - int eof; -}; - -Parser * -ParserCreate(char * str) -{ - Parser * ret; - if (!str) - { - return NULL; - } - - ret = Malloc(sizeof(Parser)); - - ret->string = StrDuplicate(str); - ret->idx = 0; - ret->eof = 0; - ret->mark = -1; - - return ret; -} - -void -ParserStartCopy(Parser * p) -{ - if (!p) - { - return; - } - p->mark = p->idx; -} -char * -ParserEndCopy(Parser * p) -{ - char *ret; - size_t len; - if (!p || p->mark < 0) - { - return NULL; - } - - len = p->idx - p->mark; - - ret = Malloc(len + 1); - memcpy(ret, p->string + p->mark, len); - ret[len] = '\0'; - - return ret; -} int -ParserExcept(Parser * p, char c) +ParseCommonID(char *str, CommonID *id) { - char strc; - if (!p || p->eof) + char sigil; + char *servstart; + + if (!str || !id) { return 0; } - - strc = p->string[p->idx++]; - if (!strc) - { - p->eof = 1; - p->idx--; /* Avoid overflows */ - } - return strc == c; -} -int -ParserExceptOneOf(Parser * p, const char * str) -{ - char strc; - if (!p || !str || p->eof) - { - return 0; - } - - strc = p->string[p->idx++]; - if (!strc) - { - p->eof = 1; - p->idx--; /* Avoid overflows */ - } - if (strchr(str, strc)) - { - return strc; - } - return 0; -} - -int -ParserGetc(Parser * p) -{ - int c; - if (!p || p->eof) - { - return EOF; - } - c = p->string[p->idx++]; - if (!c) - { - p->eof = 1; - p->idx--; /* Avoid overflows */ - c = EOF; - } - return c; -} -void -ParserUndo(Parser * p) -{ - if (!p) - { - return; - } - if (!p->idx) + /* There must at least be 2 chararacters: the sigil and a string.*/ + if (strlen(str) < 2) { - return; + return 0; } - p->eof = 0; - p->idx--; -} -void -ParserEnd(Parser * p) -{ - if (!p) + sigil = *str++; + /* Some sigils have the following restriction: + * > MUST NOT exceed 255 bytes (including the # sigil and the domain). + */ + if ((sigil == '#' || sigil == '@') && strlen(str) > 255) { - return; + return 0; } - Free(p->string); - Free(p); -} + id->sigil = sigil; + /* Find the position of a ':' if there is one. */ + if ((servstart = strchr(str, ':'))) + { + id->local = StrSubstr(str, 1, (char) (servstart - str)); + id->server = StrDuplicate(servstart + 1); + return 1; + } + /* Otherwise, just take the rest of the string. */ + id->local = StrDuplicate(str + 1) ; + id->server = NULL ; + + return 1; +} diff --git a/src/User.c b/src/User.c index 018e046..9e36239 100644 --- a/src/User.c +++ b/src/User.c @@ -31,10 +31,6 @@ #include #include -#include - -#include - #include struct User @@ -886,89 +882,51 @@ finish: return arr; } -static int -UserIdParseLocal(Parser *p, char **ret) -{ - int c; - if (!p || !ret) - { - return 0; - } - - ParserStartCopy(p); - /* Always assume the general case here: every ASCII char, - * minus ':'. */ - while (isascii((c = ParserGetc(p))) && c != ':') - { - /* Do nothing. */ - } - if (c != EOF) - { - ParserUndo(p); - } - *ret = ParserEndCopy(p); - return 1; -} -static int -UserIdParseServer(Parser *p, char **ret) -{ - int c; - if (!p || !ret) - { - return 0; - } - - ParserStartCopy(p); - /* Allow *every* ASCII character. */ - while (isascii((c = ParserGetc(p)))) - { - /* Do nothing. */ - } - if (c != EOF) - { - ParserUndo(p); - } - *ret = ParserEndCopy(p); - return 1; -} - UserId * UserIdParse(char *id, char *defaultServer) { UserId *userId; - Parser *p; if (!id) { return NULL; } - p = ParserCreate(id); - userId = Malloc(sizeof(UserId)); - userId->localpart = NULL; - userId->server = NULL; + id = StrDuplicate(id); + if (!id) + { + return NULL; + } + userId = Malloc(sizeof(UserId)); if (!userId) { goto finish; } - /* Fully-qualified user ID. - * TODO: Generalise this for parsing namespaced IDs, - * like room aliases and IDs. */ - if (ParserExcept(p, '@')) + /* Fully-qualified user ID */ + if (*id == '@') { - if (!UserIdParseLocal(p, &userId->localpart) || - !ParserExcept(p, ':') || - !UserIdParseServer(p, &userId->server)) + char *localStart = id + 1; + char *serverStart = localStart; + + while (*serverStart != ':' && *serverStart != '\0') + { + serverStart++; + } + + if (*serverStart == '\0') { - if (userId->localpart) - { - Free(userId->localpart); - } Free(userId); userId = NULL; + goto finish; } + + *serverStart = '\0'; + serverStart++; + + userId->localpart = StrDuplicate(localStart); + userId->server = StrDuplicate(serverStart); } else { @@ -984,7 +942,7 @@ UserIdParse(char *id, char *defaultServer) } finish: - ParserEnd(p); + Free(id); return userId; } diff --git a/src/include/Parser.h b/src/include/Parser.h index 6c9c281..3f7fb7e 100644 --- a/src/include/Parser.h +++ b/src/include/Parser.h @@ -26,73 +26,31 @@ /*** * @Nm Parser - * @Nd Functions for dealing with simple grammars. - * @Dd November 24 2023 + * @Nd Functions for dealing with grammars found in Matrix + * @Dd November 25 2023 * @Xr User * * The * .Nm - * API provides a simple parsing interface for basic parsers. + * API provides an interface for parsing grammars within the + * Matrix specification */ /** - * A lot of functions here use this opaque structure. + * A common identifier in the form '&local[:server]', where + * & determines the *type* of the identifier. */ -typedef struct Parser Parser; +typedef struct CommonID { + char sigil; + char *local; + char *server; /* Might be NULL for some sigils(e.g: room IDs >= v3) */ +} CommonID; -/** - * Create a new parser with an input string. +/** + * Parses a common identifier, as per the Common Identifier Format as defined + * by the [matrix] specification. */ -extern Parser * ParserCreate(char *); +extern int ParseCommonID(char *, CommonID *); -/** - * Returns true if the character at the current position in - * the parsing process is the one given in, and advances by - * one character eitherway. - */ -extern int ParserExcept(Parser *, char); - -/** - * Gets the currently pointed at character in the parser, then - * advances it by one, unless if hit by an EOF. - */ -extern int ParserGetc(Parser *); - -/** - * Rolls back the currently pointed character by one(unless already - * at the start.) - */ -extern void ParserUndo(Parser *); - -/** - * Returns a non-zero value if the character at the current position - * in the parsing process is one of the characters in the inputted - * string, and advances by one character eitherway. - * - * If non-zero, the return value is the actual character. - */ -extern int ParserExceptOneOf(Parser *, const char *); - -/** - * Starts a clipping session. This stores an index into the - * parser, until - * .Fn ParserEndCopy - * is called. - */ -extern void ParserStartCopy(Parser *); -/** - * Ends a clipping station created by - * .Fn ParserStartCopy - * if it was called beforehand into a new buffer to be freed - * with - * .Fn Free . - */ -extern char * ParserEndCopy(Parser *); - -/** - * Frees a parser created with - * .Fn ParserCreate . - */ -extern void ParserEnd(Parser *); #endif /* TELODENDRIA_PARSER_H */