forked from Telodendria/Telodendria
[MOD] Drop old Parser API, add new ID parser
This commit is contained in:
parent
4a575cee1d
commit
4298ee469a
3 changed files with 68 additions and 254 deletions
146
src/Parser.c
146
src/Parser.c
|
@ -24,149 +24,47 @@
|
||||||
|
|
||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
|
|
||||||
#include <Cytoplasm/Memory.h>
|
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
#include <Cytoplasm/Log.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
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
|
int
|
||||||
ParserExcept(Parser * p, char c)
|
ParseCommonID(char *str, CommonID *id)
|
||||||
{
|
{
|
||||||
char strc;
|
char sigil;
|
||||||
if (!p || p->eof)
|
char *servstart;
|
||||||
|
|
||||||
|
if (!str || !id)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strc = p->string[p->idx++];
|
/* There must at least be 2 chararacters: the sigil and a string.*/
|
||||||
if (!strc)
|
if (strlen(str) < 2)
|
||||||
{
|
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strc = p->string[p->idx++];
|
sigil = *str++;
|
||||||
if (!strc)
|
/* Some sigils have the following restriction:
|
||||||
|
* > MUST NOT exceed 255 bytes (including the # sigil and the domain).
|
||||||
|
*/
|
||||||
|
if ((sigil == '#' || sigil == '@') && strlen(str) > 255)
|
||||||
{
|
{
|
||||||
p->eof = 1;
|
|
||||||
p->idx--; /* Avoid overflows */
|
|
||||||
}
|
|
||||||
if (strchr(str, strc))
|
|
||||||
{
|
|
||||||
return strc;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
id->sigil = sigil;
|
||||||
|
|
||||||
int
|
/* Find the position of a ':' if there is one. */
|
||||||
ParserGetc(Parser * p)
|
if ((servstart = strchr(str, ':')))
|
||||||
{
|
{
|
||||||
int c;
|
id->local = StrSubstr(str, 1, (char) (servstart - str));
|
||||||
if (!p || p->eof)
|
id->server = StrDuplicate(servstart + 1);
|
||||||
{
|
return 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
/* Otherwise, just take the rest of the string. */
|
||||||
|
id->local = StrDuplicate(str + 1) ;
|
||||||
|
id->server = NULL ;
|
||||||
|
|
||||||
if (!p->idx)
|
return 1;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
p->eof = 0;
|
|
||||||
p->idx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ParserEnd(Parser * p)
|
|
||||||
{
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Free(p->string);
|
|
||||||
Free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
90
src/User.c
90
src/User.c
|
@ -31,10 +31,6 @@
|
||||||
#include <Cytoplasm/Int64.h>
|
#include <Cytoplasm/Int64.h>
|
||||||
#include <Cytoplasm/UInt64.h>
|
#include <Cytoplasm/UInt64.h>
|
||||||
|
|
||||||
#include <Parser.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct User
|
struct User
|
||||||
|
@ -886,89 +882,51 @@ finish:
|
||||||
return arr;
|
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 *
|
UserId *
|
||||||
UserIdParse(char *id, char *defaultServer)
|
UserIdParse(char *id, char *defaultServer)
|
||||||
{
|
{
|
||||||
UserId *userId;
|
UserId *userId;
|
||||||
Parser *p;
|
|
||||||
|
|
||||||
if (!id)
|
if (!id)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ParserCreate(id);
|
id = StrDuplicate(id);
|
||||||
userId = Malloc(sizeof(UserId));
|
if (!id)
|
||||||
userId->localpart = NULL;
|
{
|
||||||
userId->server = NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
userId = Malloc(sizeof(UserId));
|
||||||
if (!userId)
|
if (!userId)
|
||||||
{
|
{
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fully-qualified user ID.
|
/* Fully-qualified user ID */
|
||||||
* TODO: Generalise this for parsing namespaced IDs,
|
if (*id == '@')
|
||||||
* like room aliases and IDs. */
|
|
||||||
if (ParserExcept(p, '@'))
|
|
||||||
{
|
{
|
||||||
if (!UserIdParseLocal(p, &userId->localpart) ||
|
char *localStart = id + 1;
|
||||||
!ParserExcept(p, ':') ||
|
char *serverStart = localStart;
|
||||||
!UserIdParseServer(p, &userId->server))
|
|
||||||
|
while (*serverStart != ':' && *serverStart != '\0')
|
||||||
{
|
{
|
||||||
if (userId->localpart)
|
serverStart++;
|
||||||
{
|
|
||||||
Free(userId->localpart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*serverStart == '\0')
|
||||||
|
{
|
||||||
Free(userId);
|
Free(userId);
|
||||||
userId = NULL;
|
userId = NULL;
|
||||||
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*serverStart = '\0';
|
||||||
|
serverStart++;
|
||||||
|
|
||||||
|
userId->localpart = StrDuplicate(localStart);
|
||||||
|
userId->server = StrDuplicate(serverStart);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -984,7 +942,7 @@ UserIdParse(char *id, char *defaultServer)
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
ParserEnd(p);
|
Free(id);
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,73 +26,31 @@
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* @Nm Parser
|
* @Nm Parser
|
||||||
* @Nd Functions for dealing with simple grammars.
|
* @Nd Functions for dealing with grammars found in Matrix
|
||||||
* @Dd November 24 2023
|
* @Dd November 25 2023
|
||||||
* @Xr User
|
* @Xr User
|
||||||
*
|
*
|
||||||
* The
|
* The
|
||||||
* .Nm
|
* .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 */
|
#endif /* TELODENDRIA_PARSER_H */
|
||||||
|
|
Loading…
Reference in a new issue