#ifndef _GUARD_uri_h_
#define _GUARD_uri_h_
#include "ebb.h"
#include <stddef.h>
/* have to be static const char so that can use sizeof */
static const char ebb_http_404[] = "HTTP/1.0 404 Not Found\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 6\r\n\r\nfalse\n";
static const char ebb_http_empty_object[] = "HTTP/1.0 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 3\r\n\r\n{}\n";
static const char ebb_http_empty_array[] = "HTTP/1.0 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 3\r\n\r\n[]\n";
static const char ebb_http_ok_true[] = "HTTP/1.0 200 OK\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 5\r\n\r\ntrue\n";
/* we should never sizeof ebb_http_header */
extern const char ebb_http_header[];
void uri_ebb_buf_free(ebb_buf* buf);
typedef enum {
s_form_data_start,
s_form_data_header_field,
s_form_data_header_value_start,
s_form_data_header_value_name_start,
s_form_data_header_value_name_done,
s_form_data_done,
} form_data_state_t;
typedef struct {
form_data_state_t state;
char lookbehind;
int cursor;
int disposition_index;
void* context;
void (*on_name)(void*, const char*, size_t);
} form_data_parser_t;
void form_data_parser_init(form_data_parser_t* parser, void* context);
void form_data_parser_execute(form_data_parser_t* parser, const char* buf, size_t len, int header_index);
typedef enum {
s_query_string_start,
s_query_string_field_start,
s_query_string_value_start,
s_query_string_value_done,
} query_string_state_t;
typedef struct {
query_string_state_t state;
void* context;
int header_index;
void (*on_field)(void*, const char*, size_t, int);
void (*on_value)(void*, const char*, size_t, int);
} query_string_parser_t;
void query_string_parser_init(query_string_parser_t* parser, void* context);
void query_string_parser_execute(query_string_parser_t* parser, const char* buf, size_t len);
typedef enum {
s_numeric_start,
s_numeric_before_decimal,
s_numeric_after_decimal,
s_numeric_illegal,
} numeric_state_t;
typedef struct {
numeric_state_t state;
double result;
double division;
} numeric_parser_t;
void numeric_parser_init(numeric_parser_t* parser);
void numeric_parser_execute(numeric_parser_t* parser, const char* buf, size_t len);
typedef enum {
s_bool_start,
s_bool_1,
s_bool_0,
s_bool_true,
s_bool_false,
s_bool_illegal,
} bool_state_t;
typedef struct {
bool_state_t state;
int cursor;
int result;
} bool_parser_t;
void bool_parser_init(bool_parser_t* parser);
void bool_parser_execute(bool_parser_t* parser, const char* buf, size_t len);
typedef enum {
s_coord_start,
s_coord_x_before_decimal,
s_coord_x_after_decimal,
s_coord_y_before_decimal,
s_coord_y_after_decimal,
s_coord_illegal,
} coord_state_t;
typedef struct {
coord_state_t state;
double x;
double y;
double division;
} coord_parser_t;
void coord_parser_init(coord_parser_t* parser);
void coord_parser_execute(coord_parser_t* parser, const char* buf, size_t len);
typedef enum {
s_string_start,
s_string_overflow,
} string_state_t;
typedef struct {
string_state_t state;
char string[256];
int cursor;
} string_parser_t;
void string_parser_init(string_parser_t* parser);
void string_parser_execute(string_parser_t* parser, const char* buf, size_t len);
typedef struct {
ebb_buf data;
} blob_parser_t;
void blob_parser_init(blob_parser_t* parser);
void blob_parser_execute(blob_parser_t* parser, const char* buf, size_t len);
typedef enum {
URI_QUERY_STRING,
URI_CONTENT_BODY,
URI_MULTIPART_HEADER_FIELD,
URI_MULTIPART_HEADER_VALUE,
URI_MULTIPART_DATA,
URI_PARSE_TERMINATE,
} uri_parse_state_t;
typedef enum {
PARAM_TYPE_INT,
PARAM_TYPE_FLOAT,
PARAM_TYPE_DOUBLE,
PARAM_TYPE_SIZE,
PARAM_TYPE_POINT,
PARAM_TYPE_STRING,
PARAM_TYPE_BOOL,
PARAM_TYPE_BLOB,
PARAM_TYPE_BODY, // alias for BLOB, in cases that is not multi-part, this is get result from http body
PARAM_TYPE_ID, // alias for INT, in cases that is a part of uri, it will triumph any parameter passed in later
} param_type_t;
typedef struct {
char* property;
param_type_t type;
size_t offset;
void (*on_string)(void*, char*);
void (*on_blob)(void*, ebb_buf);
} param_dispatch_t;
typedef enum {
s_param_start = -1,
s_param_skip = -2,
/* the rest of the states are numerated from 0 to upper size of param_map */
} param_parse_state_t;
typedef struct {
param_parse_state_t state;
param_parse_state_t body;
param_parse_state_t resource;
form_data_parser_t form_data_parser;
query_string_parser_t query_string_parser;
int header_index;
int cursor;
char name[32];
const param_dispatch_t* param_map;
size_t len;
char* parsed;
void* context;
union {
numeric_parser_t numeric_parser;
bool_parser_t bool_parser;
coord_parser_t coord_parser;
string_parser_t string_parser;
blob_parser_t blob_parser;
};
} param_parser_t;
void param_parser_terminate(param_parser_t* parser);
int param_parser_map_alphabet(const param_dispatch_t* param_map, size_t len);
ebb_buf param_parser_map_http_body(const param_dispatch_t* param_map, size_t len, const char* response_format);
void param_parser_init(param_parser_t* parser, const param_dispatch_t* param_map, size_t len, void* parsed, void* context);
void param_parser_execute(param_parser_t* parser, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
typedef struct {
char* uri;
void* context;
void* (*init)(void); // this runs on server start
void* (*parse)(const void*, void*, int, const char*, size_t, uri_parse_state_t, int); // this runs on main thread
int (*get)(const void*, const void*, ebb_buf*); // this runs off thread
int (*post)(const void*, const void*, ebb_buf*); // this runs off thread
int (*delete)(const void*, const void*, ebb_buf*); // this runs off thread
void (*destroy)(void*); // this runs on server shutdown
} uri_dispatch_t;
uri_dispatch_t* find_uri_dispatch(const char* path);
void uri_init(void);
void uri_destroy(void);
void* uri_root_init(void);
void uri_root_destroy(void* context);
int uri_root_discovery(const void* context, const void* parsed, ebb_buf* buf);
void* uri_bbf_detect_objects_init(void);
void uri_bbf_detect_objects_destroy(void* context);
void* uri_bbf_detect_objects_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_bbf_detect_objects_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_bbf_detect_objects(const void* context, const void* parsed, ebb_buf* buf);
void* uri_dpm_detect_objects_init(void);
void uri_dpm_detect_objects_destroy(void* context);
void* uri_dpm_detect_objects_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_dpm_detect_objects_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_dpm_detect_objects(const void* context, const void* parsed, ebb_buf* buf);
void* uri_icf_detect_objects_init(void);
void uri_icf_detect_objects_destroy(void* context);
void* uri_icf_detect_objects_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_icf_detect_objects_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_icf_detect_objects(const void* context, const void* parsed, ebb_buf* buf);
void* uri_scd_detect_objects_init(void);
void uri_scd_detect_objects_destroy(void* context);
void* uri_scd_detect_objects_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_scd_detect_objects_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_scd_detect_objects(const void* context, const void* parsed, ebb_buf* buf);
void* uri_sift_init(void);
void uri_sift_destroy(void* context);
void* uri_sift_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_sift_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_sift(const void* context, const void* parsed, ebb_buf* buf);
void* uri_swt_detect_words_init(void);
void uri_swt_detect_words_destroy(void* context);
void* uri_swt_detect_words_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_swt_detect_words_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_swt_detect_words(const void* context, const void* parsed, ebb_buf* buf);
void* uri_tld_track_object_init(void);
void uri_tld_track_object_destroy(void* context);
void* uri_tld_track_object_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_tld_track_object_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_tld_track_object(const void* context, const void* parsed, ebb_buf* buf);
int uri_tld_track_object_free(const void* context, const void* parsed, ebb_buf* buf);
void* uri_convnet_classify_init(void);
void uri_convnet_classify_destroy(void* context);
void* uri_convnet_classify_parse(const void* context, void* parsed, int resource_id, const char* buf, size_t len, uri_parse_state_t state, int header_index);
int uri_convnet_classify_intro(const void* context, const void* parsed, ebb_buf* buf);
int uri_convnet_classify(const void* context, const void* parsed, ebb_buf* buf);
#endif