text: #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
  