vessel/web/include/path.h
Arija A. bf87b89080
refact: Update macro formats.
Signed-off-by: Arija A. <ari@ari.lt>
2025-06-14 16:20:50 +03:00

160 lines
5.8 KiB
C

#ifndef VESSEL_WEB_PATH_H_
#define VESSEL_WEB_PATH_H_
#include "conf.h"
#include "http.h"
#include <vessel/log.h>
#include <vessel/def.h>
#include <vessel/hmap.h>
#include <vessel/array.h>
#define VW_PATTERN_MAX_KEY 32
#define VW_PATTERN_MAX_VALUE 256
typedef struct {
char *path;
size_t len;
vs_HMap args;
} vw_Path;
bool vw_Path_init(vw_Path *path);
bool vw_Path_parse(vw_Path *path, const char *src);
bool vw_Path_destroy(vw_Path *path);
#define VW_PATH_SEGMENT_FLAG_NOCONV ((uint8_t)0x80) /* 1000 0000 => ! */
#define VW_PATH_SEGMENT_FLAG_OPTIONAL ((uint8_t)0x40) /* 0100 0000 => ? */
#define VW_PATH_SEGMENT_FLAG_STATIC ((uint8_t)0x20) /* 0010 0000 => static */
#define VW_PATH_TYPE_FLAG_LAST ((uint16_t)0x8000) /* 1000 0000 0000 0000: Last token */
#define VW_PATH_TYPE_FLAG_BOUND \
((uint16_t)0x2000) /* 0010 0000 0000 0000: Strictly bound (cannot be used \
next to adjacent dynamic segments) */
#define VW_PATH_TYPE_FLAG_NOCONV ((uint16_t)0x1000) /* 0001 0000 0000 0000: No-convert type */
#define VW_PATH_TYPE_FLAG_ALARG ((uint16_t)0x0800) /* 0000 1000 0000 0000: Require argument */
#define VW_PATH_TYPE_FLAG_REQUIRED ((uint16_t)0x0400) /* 0000 0100 0000 0000: Always required */
#define VW_PATH_TYPE_FLAG_VALIDATE_ONLY \
((uint16_t)0x0200) /* 0000 0010 0000 0000: Validate-only type */
#define VW_PATH_TYPE_FLAG_NODEFAULT \
((uint16_t)0x0100) /* 0000 0001 0000 0000: Disable default values */
#define VW_PATH_TYPE_FLAG_STRIP_SPACES_ARG \
((uint16_t)0x0080) /* 0000 0000 1000 0000: Enable space stripping in \
arguments */
#define VW_PATH_TYPE_FLAG_LOWERCASE_ARG \
((uint16_t)0x0040) /* 0000 0000 0100 0000: Enable lowercase in arguments \
*/
#define VW_PATH_TYPE_FLAG_STRIP_SPACES_VALUE \
((uint16_t)0x0040) /* 0000 0000 0010 0000: Enable space stripping in \
values */
#define VW_PATH_TYPE_FLAG_LOWERCASE_VALUE \
((uint16_t)0x0020) /* 0000 0000 0001 0000: Enable lowercase in values */
#define VW_PATH_TYPE_FLAG_ALCOMP ((uint16_t)0x0010) /* 0000 0000 0000 1000: Always compile */
#define VW_PATH_TYPE_FLAG_NOARG ((uint16_t)0x0008) /* 0000 0000 0000 0100: No argument */
#define vw__VW_PATH_TYPE_FLAG_BUILTIN_CAUTION \
((uint16_t)0x0001) /* 0000 0000 0000 0001: Built-in type (NOTE: Use with \
caution) */
/* <type[!][(arg)][:key][(?[=default]]> */
typedef struct {
char *key;
size_t key_len;
char *def; /* NOTE: Either actual default or static part */
size_t def_len;
void *def_conv;
size_t def_reqb;
bool always_insert;
uint8_t flags; /* !, ?, and static tokens are flags */
vs_HMapID type;
void *compiled;
} vw_PathSegment;
typedef struct {
const char *src;
const size_t len;
const vw_PathSegment *seg;
const bool full;
} vw_PathSource;
typedef struct {
const char *src;
const size_t len;
} vw_ArgSource;
typedef bool (*vw_PathTypeCompileFunc)(const vw_ArgSource *arg, void **comp);
typedef bool (*vw_PathTypeConsumeFunc)(const vw_PathSource *src, size_t *size, size_t *reqb);
typedef bool (*vw_PathTypeConvertFunc)(const vw_PathSource *src, size_t reqb, void *out);
typedef bool (*vw_PathTypeCleanupFunc)(void *comp);
typedef bool (*vw_PathTypePrintFunc)(const void *comp);
/*
* Flow:
*
* 1. compile() - called once to compile `arg` into memory to be used in other
* functions. Useful to compile for example regex for optimization.
* NOTE: Only called once during path compilation.
* 2. consume() - find the length of a valid matching segment. Returns false on
* no match< filling in `reqb` for required object memory in bytes and `size` to
* describe how large the matched segment is. `src` includes: src (from where to
* begin parsing), len (how many bytes max to parse), compiled (see compile()).
* NOTE: Might also get called during compilation to check default values.
* 3. convert() - convert consumed string into a native type.
* NOTE: convert() won't always get called (noconv)
* 4. cleanup() - clean up any memory allocated by compile().
* NOTE: Only called once during cleanup.
* 5. print() - called only for debug purposes to print compiled stuff.
*
* You don't need to do NULL checks.
*/
typedef struct {
uint16_t flags;
vw_PathTypeCompileFunc compile;
vw_PathTypeConsumeFunc consume;
vw_PathTypeConvertFunc convert;
vw_PathTypeCleanupFunc cleanup;
vw_PathTypePrintFunc print;
} vw_PathType;
typedef struct {
vw_PathSegment **items;
size_t size;
size_t cap;
} vw_PathPattern;
typedef struct {
char *str;
size_t size;
void *conv;
size_t reqb;
} vw_PathMatch;
vw_PathPattern *vw_PathPattern_new(void);
vw_PathSegment *vw_PathSegment_new(void);
bool vw_PathType_new(const char *name,
uint16_t flags,
vw_PathTypeCompileFunc compile,
vw_PathTypeConsumeFunc consume,
vw_PathTypeConvertFunc convert,
vw_PathTypeCleanupFunc cleanup,
vw_PathTypePrintFunc print);
vw_PathPattern *vw_PathPattern_compile(const vs_Logger *lg, const char *pat);
size_t vw_PathPattern_matchn(const vw_PathPattern *pat, vs_HMap *out, const char *src, size_t len);
bool vw_PathPattern_print(const vw_PathPattern *pat, bool show_static_bounds);
bool vw_PathPattern_destroy(vw_PathPattern *pat);
bool vw_PathPattern_matchn_destroy(vs_HMap *out);
bool vw_PathPattern_matchn_clear(vs_HMap *out);
void vw_PathPattern_matchn_print(const vs_HMap *out);
#endif /* VESSEL_WEB_PATH_H_ */