diff options
| author | bozo.kopic <bozo@kopic.xyz> | 2021-12-22 19:35:48 +0100 |
|---|---|---|
| committer | bozo.kopic <bozo@kopic.xyz> | 2021-12-22 19:35:48 +0100 |
| commit | 1a19c238e3741931db9e61b6a0b79259b5ed0753 (patch) | |
| tree | 7e5d705e423583188b346bbb7e7486f808b66bc8 /src_c | |
| parent | 923e73a50320792bbedb945b45c54dab12d44708 (diff) | |
WIP c implementation
Diffstat (limited to 'src_c')
| -rw-r--r-- | src_c/common.c | 69 | ||||
| -rw-r--r-- | src_c/common.h | 21 | ||||
| -rw-r--r-- | src_c/csp.c | 14 | ||||
| -rw-r--r-- | src_c/csp.h | 23 | ||||
| -rw-r--r-- | src_c/main.c | 145 |
5 files changed, 214 insertions, 58 deletions
diff --git a/src_c/common.c b/src_c/common.c index d7135a6..5aca7a8 100644 --- a/src_c/common.c +++ b/src_c/common.c @@ -28,7 +28,7 @@ static int write_bool(bool val, FILE *stream) { static int write_str(opcut_str_t *str, FILE *stream) { - if (fprintf(stream, "\"%*s\"", str->len, str->data) < 0) + if (fprintf(stream, "\"%.*s\"", str->len, str->data) < 0) return OPCUT_ERROR; return OPCUT_SUCCESS; @@ -36,13 +36,10 @@ static int write_str(opcut_str_t *str, FILE *stream) { static int write_panel(opcut_panel_t *panel, FILE *stream) { - if (fputs("{\"id\":", stream) < 0) - return OPCUT_ERROR; - if (write_str(&(panel->id), stream)) return OPCUT_ERROR; - if (fputs(",\"width\":", stream) < 0) + if (fputs(":{\"width\":", stream) < 0) return OPCUT_ERROR; if (write_number(panel->width, stream)) @@ -62,13 +59,10 @@ static int write_panel(opcut_panel_t *panel, FILE *stream) { static int write_item(opcut_item_t *item, FILE *stream) { - if (fputs("{\"id\":", stream) < 0) - return OPCUT_ERROR; - if (write_str(&(item->id), stream)) return OPCUT_ERROR; - if (fputs(",\"width\":", stream) < 0) + if (fputs(":{\"width\":", stream) < 0) return OPCUT_ERROR; if (write_number(item->width, stream)) @@ -106,7 +100,7 @@ static int write_params(opcut_params_t *params, FILE *stream) { if (write_bool(params->min_initial_usage, stream)) return OPCUT_ERROR; - if (fputs("\"panels\":[", stream) < 0) + if (fputs(",\"panels\":{", stream) < 0) return OPCUT_ERROR; for (size_t i = 0; i < params->panels_len; ++i) { @@ -119,7 +113,7 @@ static int write_params(opcut_params_t *params, FILE *stream) { } } - if (fputs("],\"items\":[", stream) < 0) + if (fputs("},\"items\":{", stream) < 0) return OPCUT_ERROR; for (size_t i = 0; i < params->items_len; ++i) { @@ -132,7 +126,7 @@ static int write_params(opcut_params_t *params, FILE *stream) { } } - if (fputs("]}", stream) < 0) + if (fputs("}}", stream) < 0) return OPCUT_ERROR; return OPCUT_SUCCESS; @@ -261,7 +255,7 @@ static int read_panel(char *json, opcut_panel_t *panel, jsmntok_t *tokens, if (panel_token->type != JSMN_OBJECT) return OPCUT_ERROR; - if (!read_string(json, &(panel->id), id_token)) + if (read_string(json, &(panel->id), id_token)) return OPCUT_ERROR; panel->width = 0; @@ -294,7 +288,7 @@ static int read_item(char *json, opcut_item_t *item, jsmntok_t *tokens, if (item_token->type != JSMN_OBJECT) return OPCUT_ERROR; - if (!read_string(json, &(item->id), id_token)) + if (read_string(json, &(item->id), id_token)) return OPCUT_ERROR; item->width = 0; @@ -367,7 +361,7 @@ static int read_params(char *json, opcut_params_t *params, jsmntok_t *tokens, goto error_cleanup; for (size_t j = 0; j < params->panels_len; ++j) { - if (!read_panel(json, params->panels + j, tokens, pos)) + if (read_panel(json, params->panels + j, tokens, pos)) goto error_cleanup; } @@ -386,7 +380,7 @@ static int read_params(char *json, opcut_params_t *params, jsmntok_t *tokens, goto error_cleanup; for (size_t j = 0; j < params->items_len; ++j) { - if (!read_item(json, params->items + j, tokens, pos)) + if (read_item(json, params->items + j, tokens, pos)) goto error_cleanup; } } @@ -409,6 +403,16 @@ error_cleanup: } +int opcut_str_resize(opcut_str_t *str, size_t size) { + char *data = realloc(str->data, size); + if (!data) + return OPCUT_ERROR; + + str->data = data; + return OPCUT_SUCCESS; +} + + int opcut_params_init(opcut_params_t *params, opcut_str_t *json) { jsmn_parser parser; int tokens_len; @@ -432,15 +436,6 @@ int opcut_params_init(opcut_params_t *params, opcut_str_t *json) { } -void opcut_params_destroy(opcut_params_t *params) { - if (params->panels) - free(params->panels); - - if (params->items) - free(params->items); -} - - int opcut_result_write(opcut_result_t *result, FILE *stream) { if (fputs("{\"params\":", stream) < 0) return OPCUT_ERROR; @@ -479,3 +474,27 @@ int opcut_result_write(opcut_result_t *result, FILE *stream) { return OPCUT_SUCCESS; } + + +void opcut_str_destroy(opcut_str_t *str) { + if (str->data) + free(str->data); +} + + +void opcut_params_destroy(opcut_params_t *params) { + if (params->panels) + free(params->panels); + + if (params->items) + free(params->items); +} + + +void opcut_result_destroy(opcut_result_t *result) { + if (result->used) + free(result->used); + + if (result->unused) + free(result->unused); +} diff --git a/src_c/common.h b/src_c/common.h index 16aeb9b..42fed63 100644 --- a/src_c/common.h +++ b/src_c/common.h @@ -8,6 +8,21 @@ #define OPCUT_ERROR 1 #define OPCUT_UNSOLVABLE 2 +#define OPCUT_STR_EMPTY ((opcut_str_t){.data = NULL, .len = 0}) +#define OPCUT_PARAMS_EMPTY \ + ((opcut_params_t){.cut_width = 0, \ + .min_initial_usage = false, \ + .panels = NULL, \ + .panels_len = 0, \ + .items = NULL, \ + .items_len = 0}) +#define OPCUT_RESULT_EMPTY \ + ((opcut_result_t){.params = NULL, \ + .used = NULL, \ + .used_len = 0, \ + .unused = NULL, \ + .unused_len = 0}) + #ifdef __cplusplus extern "C" { #endif @@ -64,10 +79,14 @@ typedef struct { } opcut_result_t; +int opcut_str_resize(opcut_str_t *str, size_t size); int opcut_params_init(opcut_params_t *params, opcut_str_t *json); -void opcut_params_destroy(opcut_params_t *params); int opcut_result_write(opcut_result_t *result, FILE *stream); +void opcut_str_destroy(opcut_str_t *str); +void opcut_params_destroy(opcut_params_t *params); +void opcut_result_destroy(opcut_result_t *result); + #ifdef __cplusplus } #endif diff --git a/src_c/csp.c b/src_c/csp.c new file mode 100644 index 0000000..1e555dc --- /dev/null +++ b/src_c/csp.c @@ -0,0 +1,14 @@ +#include "csp.h" + + +int opcut_calculate(opcut_method_t method, opcut_params_t *params, + opcut_result_t *result) { + + result->params = params; + result->used = NULL; + result->used_len = 0; + result->unused = NULL; + result->unused_len = 0; + + return OPCUT_SUCCESS; +} diff --git a/src_c/csp.h b/src_c/csp.h new file mode 100644 index 0000000..2cccf50 --- /dev/null +++ b/src_c/csp.h @@ -0,0 +1,23 @@ +#ifndef OPCUT_POOL_H +#define OPCUT_POOL_H + +#include <stddef.h> +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + OPCUT_METHOD_GREEDY, + OPCUT_METHOD_FORWARD_GREEDY +} opcut_method_t; + +int opcut_calculate(opcut_method_t method, opcut_params_t *params, + opcut_result_t *result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src_c/main.c b/src_c/main.c index 9cc71ed..9648f7c 100644 --- a/src_c/main.c +++ b/src_c/main.c @@ -1,24 +1,74 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <argparse.h> #include "common.h" +#include "csp.h" -static int read_stdin(opcut_str_t *json) { - size_t json_data_size = 0; - json->data = NULL; - json->len = 0; +typedef struct { + opcut_method_t method; + char *input_path; + char *output_path; +} args_t; - while (!(json->len < json_data_size)) { - char *old_json_data = json->data; - json_data_size += 4096; - json->data = realloc(json->data, json_data_size); - if (!json->data) { - free(old_json_data); - return OPCUT_ERROR; + +static int parse_args(args_t *args, int argc, char **argv) { + char *method = NULL; + char *output_path = NULL; + + char *usages[] = { + "opcut-calculate [options] [[--] -|path]", + NULL, + }; + + struct argparse_option options[] = { + OPT_HELP(), OPT_STRING(0, "method", &method, "calculate method"), + OPT_STRING(0, "output", &output_path, "output path"), OPT_END()}; + + struct argparse argparse; + argparse_init(&argparse, options, (const char *const *)usages, 0); + argc = argparse_parse(&argparse, argc, (const char **)argv); + + if (method && strcmp(method, "greedy") == 0) { + args->method = OPCUT_METHOD_GREEDY; + } else if (method && strcmp(method, "forward_greedy") == 0) { + args->method = OPCUT_METHOD_FORWARD_GREEDY; + } else { + return OPCUT_ERROR; + } + + if (!argc) { + args->input_path = NULL; + } else if (argc == 1) { + if (strcmp(argv[0], "-") == 0) { + args->input_path = NULL; + } else { + args->input_path = argv[0]; } - json->len += - fread(json->data + json->len, 1, json_data_size - json->len, stdin); + } else { + return OPCUT_ERROR; + } + + if (output_path && strcmp(output_path, "-") == 0) { + args->output_path = NULL; + } else { + args->output_path = output_path; + } + + return OPCUT_SUCCESS; +} + + +static int read_stream(FILE *stream, opcut_str_t *json) { + size_t size = 0; + + while (!(json->len < size)) { + size += 4096; + if (opcut_str_resize(json, size)) + return OPCUT_ERROR; + + json->len += fread(json->data + json->len, 1, size - json->len, stream); } return OPCUT_SUCCESS; @@ -26,32 +76,63 @@ static int read_stdin(opcut_str_t *json) { int main(int argc, char **argv) { - char *method = NULL; - for (size_t i = 1; i < argc - 1; ++i) { - if (strcmp("--method", argv[i]) == 0) - method = argv[++i]; + args_t args; + FILE *input_stream = NULL; + FILE *output_stream = NULL; + opcut_str_t json = OPCUT_STR_EMPTY; + opcut_params_t params = OPCUT_PARAMS_EMPTY; + opcut_result_t result = OPCUT_RESULT_EMPTY; + int exit_code; + + exit_code = parse_args(&args, argc, argv); + if (exit_code) { + fprintf(stderr, "error parsing command line arguments\n"); + goto cleanup; } - opcut_str_t json; - if (!read_stdin(&json)) - return OPCUT_ERROR; + input_stream = (args.input_path ? fopen(args.input_path, "r") : stdin); + if (!input_stream) { + fprintf(stderr, "error opening input stream\n"); + exit_code = OPCUT_ERROR; + goto cleanup; + } - opcut_params_t params; - if (!opcut_params_init(¶ms, &json)) { - free(json.data); - return OPCUT_ERROR; + output_stream = (args.output_path ? fopen(args.output_path, "w") : stdout); + if (!output_stream) { + fprintf(stderr, "error opening output stream\n"); + exit_code = OPCUT_ERROR; + goto cleanup; + } + + exit_code = read_stream(input_stream, &json); + if (exit_code) { + fprintf(stderr, "error reading input stream\n"); + goto cleanup; + } + + exit_code = opcut_params_init(¶ms, &json); + if (exit_code) { + fprintf(stderr, "error parsing calculation parameters\n"); + goto cleanup; + } + + exit_code = opcut_calculate(args.method, ¶ms, &result); + if (exit_code) { + fprintf(stderr, "calculation error\n"); + goto cleanup; } - opcut_result_t result = {.params = ¶ms, - .used = NULL, - .used_len = 0, - .unused = NULL, - .unused_len = 0}; + exit_code = opcut_result_write(&result, output_stream); - size_t res = opcut_result_write(&result, stdout); +cleanup: + opcut_result_destroy(&result); opcut_params_destroy(¶ms); - free(json.data); + opcut_str_destroy(&json); + if (output_stream) + fclose(output_stream); + if (input_stream) + fclose(input_stream); - return res; + return exit_code; } |
