mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-05-10 13:24:06 +02:00
update build, silent folders, use threads
This commit is contained in:
parent
f8438c591b
commit
2b1b536172
@ -9,10 +9,13 @@
|
|||||||
# NOTICE that `RELEASE=1` is __after__ `make`
|
# NOTICE that `RELEASE=1` is __after__ `make`
|
||||||
#
|
#
|
||||||
|
|
||||||
|
MAKEFLAGS += -j $(shell nproc)
|
||||||
|
|
||||||
C_FLAGS = \
|
C_FLAGS = \
|
||||||
-std=c17 \
|
-std=c17 \
|
||||||
-Wall -Wextra -Wpedantic -Wconversion \
|
-Wall -Wextra -Wpedantic -Wconversion \
|
||||||
-pedantic -pedantic-errors \
|
-pedantic -pedantic-errors \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
|
||||||
L_FLAGS = -lm -pthread $(shell pkg-config sqlite3 openssl --libs)
|
L_FLAGS = -lm -pthread $(shell pkg-config sqlite3 openssl --libs)
|
||||||
C_FLAGS = $(shell pkg-config sqlite3 openssl --cflags)
|
C_FLAGS = $(shell pkg-config sqlite3 openssl --cflags)
|
||||||
@ -38,13 +41,15 @@ O_FILES = $(patsubst src/%.c,build/%.o,$(C_FILES))
|
|||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
all: server
|
TARGET=server
|
||||||
|
|
||||||
server: $(O_FILES)
|
all: build/$(TARGET)
|
||||||
$(CC) -o build/$@ $^ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
|
||||||
|
build/$(TARGET): $(O_FILES)
|
||||||
|
$(CC) -o $@ $^ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
build/%.o: src/%.c $(HEADERS)
|
build/%.o: src/%.c $(HEADERS)
|
||||||
mkdir -p $(@D)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $< -c -o $@ $(C_FLAGS) $(OPTIMIZATION) $(F_FLAGS)
|
$(CC) $< -c -o $@ $(C_FLAGS) $(OPTIMIZATION) $(F_FLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -6,4 +6,5 @@ xc
|
|||||||
-Wconversion
|
-Wconversion
|
||||||
-pedantic
|
-pedantic
|
||||||
-pedantic-errors
|
-pedantic-errors
|
||||||
|
-Wno-unused-parameter
|
||||||
|
|
||||||
|
@ -10,6 +10,14 @@ typedef struct {
|
|||||||
Db* db;
|
Db* db;
|
||||||
} Cx;
|
} Cx;
|
||||||
|
|
||||||
|
void route_get_index(HttpCtx* ctx);
|
||||||
|
void route_post_set_number(HttpCtx* ctx);
|
||||||
|
void route_get_not_found(HttpCtx* ctx);
|
||||||
|
|
||||||
|
void route_get_products_all(HttpCtx* ctx);
|
||||||
|
|
||||||
|
void route_post_user_register(HttpCtx* ctx);
|
||||||
|
|
||||||
#define RESPOND(HTTP_CTX, STATUS, MIME_TYPE, ...) \
|
#define RESPOND(HTTP_CTX, STATUS, MIME_TYPE, ...) \
|
||||||
{ \
|
{ \
|
||||||
HttpCtx* _ctx = (HTTP_CTX); \
|
HttpCtx* _ctx = (HTTP_CTX); \
|
||||||
@ -30,4 +38,5 @@ typedef struct {
|
|||||||
#define RESPOND_JSON(HTTP_CTX, STATUS, ...) \
|
#define RESPOND_JSON(HTTP_CTX, STATUS, ...) \
|
||||||
RESPOND(HTTP_CTX, STATUS, "application/json", __VA_ARGS__)
|
RESPOND(HTTP_CTX, STATUS, "application/json", __VA_ARGS__)
|
||||||
|
|
||||||
void route_get_products_all(HttpCtx* ctx);
|
#define RESPOND_BAD_REQUEST(HTTP_CTX) \
|
||||||
|
RESPOND_JSON(HTTP_CTX, 400, "{\"ok\":false}")
|
||||||
|
@ -10,7 +10,7 @@ void route_get_products_all(HttpCtx* ctx)
|
|||||||
ProductVec products;
|
ProductVec products;
|
||||||
product_vec_construct(&products);
|
product_vec_construct(&products);
|
||||||
|
|
||||||
DbRes db_res = db_product_all_fill(cx->db, &products);
|
DbRes db_res = db_product_all(cx->db, &products);
|
||||||
if (db_res != DbRes_Ok) {
|
if (db_res != DbRes_Ok) {
|
||||||
RESPOND_JSON(ctx, 500, "{\"ok\":false,\"msg\":\"db error\"}");
|
RESPOND_JSON(ctx, 500, "{\"ok\":false,\"msg\":\"db error\"}");
|
||||||
return;
|
return;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
#include "models.h"
|
#include "models.h"
|
||||||
|
|
||||||
|
DEFINE_VEC(int64_t, Ids, ids, 8)
|
||||||
DEFINE_VEC(Product, ProductVec, product_vec, 32)
|
DEFINE_VEC(Product, ProductVec, product_vec, 32)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -16,5 +17,8 @@ typedef struct Db Db;
|
|||||||
/// `user.id` field is ignored.
|
/// `user.id` field is ignored.
|
||||||
DbRes db_user_insert(Db* db, User* user);
|
DbRes db_user_insert(Db* db, User* user);
|
||||||
DbRes db_user_from_id(Db* db, User* user, int64_t id);
|
DbRes db_user_from_id(Db* db, User* user, int64_t id);
|
||||||
|
/// Expects `ids` to be constructed.
|
||||||
|
DbRes db_users_with_email(Db* db, Ids* ids, const char* email);
|
||||||
|
|
||||||
DbRes db_product_all_fill(Db* db, ProductVec* vec);
|
/// Expects `vec` to be constructed.
|
||||||
|
DbRes db_product_all(Db* db, ProductVec* vec);
|
||||||
|
@ -139,7 +139,39 @@ l0_return:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbRes db_product_all_fill(Db* db, ProductVec* vec)
|
DbRes db_users_with_email(Db* db, Ids* ids, const char* email)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(User) == 40, "model has changed");
|
||||||
|
|
||||||
|
sqlite3* connection;
|
||||||
|
CONNECT;
|
||||||
|
DbRes res;
|
||||||
|
int sqlite_res;
|
||||||
|
|
||||||
|
sqlite3_stmt* stmt;
|
||||||
|
sqlite_res = sqlite3_prepare_v2(
|
||||||
|
connection, "SELECT id FROM users WHERE email = ?", -1, &stmt, NULL);
|
||||||
|
sqlite3_bind_text(stmt, 1, email, -1, NULL);
|
||||||
|
|
||||||
|
while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||||
|
int64_t id = GET_INT(0);
|
||||||
|
ids_push(ids, id);
|
||||||
|
}
|
||||||
|
if (sqlite_res != SQLITE_DONE) {
|
||||||
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
||||||
|
res = DbRes_Error;
|
||||||
|
goto l0_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DbRes_Ok;
|
||||||
|
l0_return:
|
||||||
|
if (stmt)
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
DISCONNECT;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DbRes db_product_all(Db* db, ProductVec* vec)
|
||||||
{
|
{
|
||||||
sqlite3* connection;
|
sqlite3* connection;
|
||||||
CONNECT;
|
CONNECT;
|
||||||
|
@ -130,6 +130,11 @@ void* http_ctx_user_ctx(HttpCtx* ctx)
|
|||||||
return ctx->user_ctx;
|
return ctx->user_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* http_ctx_req_path(HttpCtx* ctx)
|
||||||
|
{
|
||||||
|
return ctx->req->path;
|
||||||
|
}
|
||||||
|
|
||||||
bool http_ctx_req_headers_has(HttpCtx* ctx, const char* key)
|
bool http_ctx_req_headers_has(HttpCtx* ctx, const char* key)
|
||||||
{
|
{
|
||||||
return req_has_header(ctx->req, key);
|
return req_has_header(ctx->req, key);
|
||||||
@ -274,7 +279,7 @@ static inline void worker_handle_request(Worker* worker, Client* client)
|
|||||||
MAX_HEADER_BUFFER_SIZE);
|
MAX_HEADER_BUFFER_SIZE);
|
||||||
goto l0_return;
|
goto l0_return;
|
||||||
}
|
}
|
||||||
puts((char*)buffer);
|
// puts((char*)buffer);
|
||||||
|
|
||||||
Req req;
|
Req req;
|
||||||
size_t body_idx;
|
size_t body_idx;
|
||||||
@ -309,6 +314,8 @@ static inline void worker_handle_request(Worker* worker, Client* client)
|
|||||||
|
|
||||||
header_vec_construct(&handler_ctx.res_headers);
|
header_vec_construct(&handler_ctx.res_headers);
|
||||||
|
|
||||||
|
bool been_handled = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < worker->ctx->server->handlers.size; ++i) {
|
for (size_t i = 0; i < worker->ctx->server->handlers.size; ++i) {
|
||||||
Handler* handler = &worker->ctx->server->handlers.data[i];
|
Handler* handler = &worker->ctx->server->handlers.data[i];
|
||||||
if (handler->method != req.method)
|
if (handler->method != req.method)
|
||||||
@ -316,9 +323,14 @@ static inline void worker_handle_request(Worker* worker, Client* client)
|
|||||||
if (strcmp(handler->path, req.path) != 0)
|
if (strcmp(handler->path, req.path) != 0)
|
||||||
continue;
|
continue;
|
||||||
handler->handler(&handler_ctx);
|
handler->handler(&handler_ctx);
|
||||||
|
been_handled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!been_handled && worker->ctx->server->not_found_handler != NULL) {
|
||||||
|
worker->ctx->server->not_found_handler(&handler_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
l1_return:
|
l1_return:
|
||||||
header_vec_destroy(&handler_ctx.res_headers);
|
header_vec_destroy(&handler_ctx.res_headers);
|
||||||
req_destroy(&req);
|
req_destroy(&req);
|
||||||
@ -333,11 +345,11 @@ static inline int parse_header(
|
|||||||
{
|
{
|
||||||
StrSplitter splitter = str_split(buf, buf_size, "\r\n");
|
StrSplitter splitter = str_split(buf, buf_size, "\r\n");
|
||||||
|
|
||||||
StrSlice first = strsplit_next(&splitter);
|
StrSlice req_line = strsplit_next(&splitter);
|
||||||
StrSplitter first_splitter = str_split(first.ptr, first.len, " ");
|
StrSplitter req_line_splitter = str_split(req_line.ptr, req_line.len, " ");
|
||||||
StrSlice method_str = strsplit_next(&first_splitter);
|
StrSlice method_str = strsplit_next(&req_line_splitter);
|
||||||
StrSlice path_str = strsplit_next(&first_splitter);
|
StrSlice uri_str = strsplit_next(&req_line_splitter);
|
||||||
StrSlice version_str = strsplit_next(&first_splitter);
|
StrSlice version_str = strsplit_next(&req_line_splitter);
|
||||||
|
|
||||||
if (strncmp(version_str.ptr, "HTTP/1.1", 8) != 0) {
|
if (strncmp(version_str.ptr, "HTTP/1.1", 8) != 0) {
|
||||||
fprintf(stderr, "error: unrecognized http version '%.*s'\n",
|
fprintf(stderr, "error: unrecognized http version '%.*s'\n",
|
||||||
@ -356,14 +368,32 @@ static inline int parse_header(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path_str.len >= MAX_PATH_LEN + 1) {
|
if (uri_str.len >= MAX_PATH_LEN + 1) {
|
||||||
fprintf(stderr, "error: path too long\n");
|
fprintf(stderr, "error: path too long\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* path = calloc(MAX_PATH_LEN + 1, sizeof(char));
|
size_t path_len = 0;
|
||||||
strncpy(path, path_str.ptr, path_str.len);
|
while (path_len < uri_str.len && uri_str.ptr[path_len] != '?'
|
||||||
path[path_str.len] = '\0';
|
&& uri_str.ptr[path_len] != '#') {
|
||||||
|
path_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* path = calloc(path_len + 1, sizeof(char));
|
||||||
|
strncpy(path, uri_str.ptr, path_len);
|
||||||
|
path[path_len] = '\0';
|
||||||
|
|
||||||
|
char* query = NULL;
|
||||||
|
if (path_len < uri_str.len) {
|
||||||
|
size_t query_len = 0;
|
||||||
|
while (path_len + query_len < uri_str.len
|
||||||
|
&& uri_str.ptr[path_len + query_len] != '#') {
|
||||||
|
query_len += 1;
|
||||||
|
}
|
||||||
|
query = calloc(query_len + 1, sizeof(char));
|
||||||
|
strncpy(query, &uri_str.ptr[path_len], query_len);
|
||||||
|
query[query_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
HeaderVec headers;
|
HeaderVec headers;
|
||||||
header_vec_construct(&headers);
|
header_vec_construct(&headers);
|
||||||
@ -402,7 +432,7 @@ static inline int parse_header(
|
|||||||
header_vec_push(&headers, (Header) { key, value });
|
header_vec_push(&headers, (Header) { key, value });
|
||||||
}
|
}
|
||||||
|
|
||||||
*req = (Req) { method, path, headers };
|
*req = (Req) { method, path, query, headers };
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ void http_server_post(
|
|||||||
void http_server_set_not_found(HttpServer* server, HttpHandlerFn handler);
|
void http_server_set_not_found(HttpServer* server, HttpHandlerFn handler);
|
||||||
|
|
||||||
void* http_ctx_user_ctx(HttpCtx* ctx);
|
void* http_ctx_user_ctx(HttpCtx* ctx);
|
||||||
|
const char* http_ctx_req_path(HttpCtx* ctx);
|
||||||
bool http_ctx_req_headers_has(HttpCtx* ctx, const char* key);
|
bool http_ctx_req_headers_has(HttpCtx* ctx, const char* key);
|
||||||
const char* http_ctx_req_headers_get(HttpCtx* ctx, const char* key);
|
const char* http_ctx_req_headers_get(HttpCtx* ctx, const char* key);
|
||||||
const char* http_ctx_req_body(HttpCtx* ctx);
|
const char* http_ctx_req_body(HttpCtx* ctx);
|
||||||
|
@ -47,6 +47,7 @@ static inline void worker_handle_request(Worker* worker, Client* req);
|
|||||||
#define MAX_HEADER_BUFFER_SIZE 8192
|
#define MAX_HEADER_BUFFER_SIZE 8192
|
||||||
|
|
||||||
#define MAX_PATH_LEN 128 - 1
|
#define MAX_PATH_LEN 128 - 1
|
||||||
|
#define MAX_QUERY_LEN 128 - 1
|
||||||
#define MAX_HEADERS_LEN 32
|
#define MAX_HEADERS_LEN 32
|
||||||
#define MAX_HEADER_KEY_LEN 32 - 1
|
#define MAX_HEADER_KEY_LEN 32 - 1
|
||||||
#define MAX_HEADER_VALUE_LEN 512 - 1
|
#define MAX_HEADER_VALUE_LEN 512 - 1
|
||||||
@ -66,6 +67,7 @@ DEFINE_VEC(Header, HeaderVec, header_vec, 8)
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Method method;
|
Method method;
|
||||||
char* path;
|
char* path;
|
||||||
|
char* query;
|
||||||
HeaderVec headers;
|
HeaderVec headers;
|
||||||
} Req;
|
} Req;
|
||||||
|
|
||||||
|
@ -8,42 +8,6 @@
|
|||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void route_get_index(HttpCtx* ctx)
|
|
||||||
{
|
|
||||||
Cx* cx = http_ctx_user_ctx(ctx);
|
|
||||||
|
|
||||||
RESPOND_HTML(ctx, 200,
|
|
||||||
"<!DOCTYPE html><html><head><meta "
|
|
||||||
"charset=\"utf-8\"></head><body><h1>Number = %d</h1></body></html>",
|
|
||||||
cx->number);
|
|
||||||
}
|
|
||||||
|
|
||||||
void route_post_set_number(HttpCtx* ctx)
|
|
||||||
{
|
|
||||||
Cx* cx = http_ctx_user_ctx(ctx);
|
|
||||||
|
|
||||||
const char* body_text = http_ctx_req_body(ctx);
|
|
||||||
JsonParser parser;
|
|
||||||
json_parser_construct(&parser, body_text, strlen(body_text));
|
|
||||||
JsonValue* body = json_parser_parse(&parser);
|
|
||||||
json_parser_destroy(&parser);
|
|
||||||
|
|
||||||
if (!json_object_has(body, "value")) {
|
|
||||||
RESPOND_JSON(
|
|
||||||
ctx, 200, "{\"ok\": false, \"msg\": \"no 'value' key\"}\r\n");
|
|
||||||
goto l0_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t value = json_int(json_object_get(body, "value"));
|
|
||||||
cx->number = (int)value;
|
|
||||||
|
|
||||||
RESPOND_JSON(ctx, 200, "{\"ok\": true}\r\n");
|
|
||||||
|
|
||||||
l0_return:
|
|
||||||
json_free(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpServer* server;
|
HttpServer* server;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
@ -65,11 +29,15 @@ int main(void)
|
|||||||
|
|
||||||
http_server_set_user_ctx(server, &cx);
|
http_server_set_user_ctx(server, &cx);
|
||||||
|
|
||||||
http_server_get(server, "/products/all", route_get_products_all);
|
http_server_get(server, "/api/products/all", route_get_products_all);
|
||||||
|
|
||||||
|
http_server_post(server, "/api/users/register", route_post_user_register);
|
||||||
|
|
||||||
http_server_get(server, "/", route_get_index);
|
http_server_get(server, "/", route_get_index);
|
||||||
http_server_post(server, "/set_number", route_post_set_number);
|
http_server_post(server, "/set_number", route_post_set_number);
|
||||||
|
|
||||||
|
http_server_set_not_found(server, route_get_not_found);
|
||||||
|
|
||||||
printf("listening at http://127.0.0.1:8080/\n");
|
printf("listening at http://127.0.0.1:8080/\n");
|
||||||
http_server_listen(server);
|
http_server_listen(server);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "models.h"
|
#include "models.h"
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
#include "models_json.h"
|
||||||
#include "str_util.h"
|
#include "str_util.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -7,6 +8,8 @@
|
|||||||
|
|
||||||
void user_free(User* m)
|
void user_free(User* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(User) == 40, "model has changed");
|
||||||
|
|
||||||
free(m->name);
|
free(m->name);
|
||||||
free(m->email);
|
free(m->email);
|
||||||
free(m->password_hash);
|
free(m->password_hash);
|
||||||
@ -14,30 +17,57 @@ void user_free(User* m)
|
|||||||
|
|
||||||
void coord_free(Coord* m)
|
void coord_free(Coord* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(Coord) == 24, "model has changed");
|
||||||
|
|
||||||
(void)m;
|
(void)m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void product_free(Product* m)
|
void product_free(Product* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(Product) == 40, "model has changed");
|
||||||
|
|
||||||
free(m->name);
|
free(m->name);
|
||||||
free(m->barcode);
|
free(m->barcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void product_price_free(ProductPrice* m)
|
void product_price_free(ProductPrice* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(ProductPrice) == 24, "model has changed");
|
||||||
|
|
||||||
(void)m;
|
(void)m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cart_free(Cart* m)
|
void cart_free(Cart* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(Cart) == 16, "model has changed");
|
||||||
|
|
||||||
(void)m;
|
(void)m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cart_item_free(CartItem* m)
|
void cart_item_free(CartItem* m)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(CartItem) == 24, "model has changed");
|
||||||
|
|
||||||
(void)m;
|
(void)m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void users_register_req_free(UsersRegisterReq* model)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(UsersRegisterReq) == 24, "model has changed");
|
||||||
|
|
||||||
|
free(model->name);
|
||||||
|
free(model->email);
|
||||||
|
free(model->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void auth_login_req_free(AuthLoginReq* model)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(AuthLoginReq) == 16, "model has changed");
|
||||||
|
|
||||||
|
free(model->email);
|
||||||
|
free(model->password);
|
||||||
|
}
|
||||||
|
|
||||||
char* user_to_json_string(const User* m)
|
char* user_to_json_string(const User* m)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(User) == 40, "model has changed");
|
static_assert(sizeof(User) == 40, "model has changed");
|
||||||
@ -155,6 +185,43 @@ char* cart_item_to_json_string(const CartItem* m)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* users_register_req_to_json(const UsersRegisterReq* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(UsersRegisterReq) == 24, "model has changed");
|
||||||
|
|
||||||
|
String string;
|
||||||
|
string_construct(&string);
|
||||||
|
string_pushf(&string,
|
||||||
|
"{"
|
||||||
|
"\"name\":\"%s\","
|
||||||
|
"\"email\":\"%s\","
|
||||||
|
"\"password\":\"%s\""
|
||||||
|
"}",
|
||||||
|
m->name, m->email, m->password);
|
||||||
|
|
||||||
|
char* result = string_copy(&string);
|
||||||
|
string_destroy(&string);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* auth_login_req_to_json(const AuthLoginReq* m)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(AuthLoginReq) == 16, "model has changed");
|
||||||
|
|
||||||
|
String string;
|
||||||
|
string_construct(&string);
|
||||||
|
string_pushf(&string,
|
||||||
|
"{"
|
||||||
|
"\"email\":\"%s\","
|
||||||
|
"\"password\":\"%s\""
|
||||||
|
"}",
|
||||||
|
m->email, m->password);
|
||||||
|
|
||||||
|
char* result = string_copy(&string);
|
||||||
|
string_destroy(&string);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* key;
|
const char* key;
|
||||||
JsonType type;
|
JsonType type;
|
||||||
@ -299,3 +366,39 @@ int cart_item_from_json(CartItem* m, const JsonValue* json)
|
|||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int users_register_req_from_json(UsersRegisterReq* m, const JsonValue* json)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(UsersRegisterReq) == 24, "model has changed");
|
||||||
|
|
||||||
|
ObjField fields[] = {
|
||||||
|
{ "name", JsonType_String },
|
||||||
|
{ "email", JsonType_String },
|
||||||
|
{ "password", JsonType_String },
|
||||||
|
};
|
||||||
|
if (!obj_conforms(json, fields, sizeof(fields) / sizeof(fields[0])))
|
||||||
|
return -1;
|
||||||
|
*m = (UsersRegisterReq) {
|
||||||
|
.name = GET_STR("name"),
|
||||||
|
.email = GET_STR("email"),
|
||||||
|
.password = GET_STR("password"),
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int auth_login_req_from_json(AuthLoginReq* m, const JsonValue* json)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(AuthLoginReq) == 16, "model has changed");
|
||||||
|
|
||||||
|
ObjField fields[] = {
|
||||||
|
{ "email", JsonType_String },
|
||||||
|
{ "password", JsonType_String },
|
||||||
|
};
|
||||||
|
if (!obj_conforms(json, fields, sizeof(fields) / sizeof(fields[0])))
|
||||||
|
return -1;
|
||||||
|
*m = (AuthLoginReq) {
|
||||||
|
.email = GET_STR("email"),
|
||||||
|
.password = GET_STR("password"),
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -47,3 +47,19 @@ void product_free(Product* model);
|
|||||||
void product_price_free(ProductPrice* model);
|
void product_price_free(ProductPrice* model);
|
||||||
void cart_free(Cart* model);
|
void cart_free(Cart* model);
|
||||||
void cart_item_free(CartItem* model);
|
void cart_item_free(CartItem* model);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
char* email;
|
||||||
|
char* password;
|
||||||
|
} UsersRegisterReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* email;
|
||||||
|
char* password;
|
||||||
|
} AuthLoginReq;
|
||||||
|
|
||||||
|
void users_register_req_free(UsersRegisterReq* model);
|
||||||
|
void auth_login_req_free(AuthLoginReq* model);
|
||||||
|
@ -11,3 +11,6 @@ DEFINE_MODEL_JSON(Product, product)
|
|||||||
DEFINE_MODEL_JSON(ProductPrice, product_price)
|
DEFINE_MODEL_JSON(ProductPrice, product_price)
|
||||||
DEFINE_MODEL_JSON(Cart, cart)
|
DEFINE_MODEL_JSON(Cart, cart)
|
||||||
DEFINE_MODEL_JSON(CartItem, cart_item)
|
DEFINE_MODEL_JSON(CartItem, cart_item)
|
||||||
|
|
||||||
|
DEFINE_MODEL_JSON(UsersRegisterReq, users_register_req)
|
||||||
|
DEFINE_MODEL_JSON(AuthLoginReq, auth_login_req)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user