Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
arg-parser: offer more apis
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Aug 29, 2024
1 parent 2cb04a7 commit 2688fd0
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 44 deletions.
23 changes: 15 additions & 8 deletions include/libtrx/arg_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
typedef enum {
ARG_PARSER_TYPE_BOOL,
ARG_PARSER_TYPE_STRING,
ARG_PARSER_TYPE_INT,
ARG_PARSER_TYPE_FLOAT,
ARG_PARSER_TYPE_INTEGER,
ARG_PARSER_TYPE_DECIMAL,
} ARG_PARSER_TYPE;

typedef struct {
char *id;
bool is_named;
char *short_name; // for named arguments like -v
char *long_name; // for named arguments like --verbose
ARG_PARSER_TYPE type;
bool mandatory;
ARG_PARSER_TYPE type;

bool provided;
struct {
bool bool_val;
char *string_val;
int32_t int_val;
float float_val;
bool val_bool;
char *val_string;
int32_t val_integer;
float val_decimal;
} value;
bool provided;
} ARG_PARSER_ARGUMENT;

typedef struct {
Expand All @@ -32,6 +33,12 @@ typedef struct {
int32_t capacity;
} ARG_PARSER;

bool ArgParser_ParseBool(const char *const value, bool *const target);
bool ArgParser_ParseInteger(const char *const value, int32_t *const target);
bool ArgParser_ParseDecimal(const char *const value, float *const target);
bool ArgParser_ParseString(
const char *const value, char **const target, bool allow_empty);

void ArgParser_Init(ARG_PARSER *const parser);
void ArgParser_Destroy(ARG_PARSER *const parser);

Expand Down
113 changes: 77 additions & 36 deletions src/arg_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,16 @@ static void ArgParser_FillValue(
{
switch (target->type) {
case ARG_PARSER_TYPE_BOOL:
target->value.bool_val =
(strcmp(value, "1") == 0 || strcmp(value, "on") == 0);
ArgParser_ParseBool(value, &target->value.val_bool);
break;
case ARG_PARSER_TYPE_STRING:
target->value.string_val = Memory_DupStr(value);
case ARG_PARSER_TYPE_INTEGER:
ArgParser_ParseInteger(value, &target->value.val_integer);
break;
case ARG_PARSER_TYPE_INT:
target->value.int_val = atoi(value);
case ARG_PARSER_TYPE_DECIMAL:
ArgParser_ParseDecimal(value, &target->value.val_decimal);
break;
case ARG_PARSER_TYPE_FLOAT:
target->value.float_val = atof(value);
case ARG_PARSER_TYPE_STRING:
ArgParser_ParseString(value, &target->value.val_string, true);
break;
}
}
Expand All @@ -119,39 +118,81 @@ static bool ArgParser_ValueMatches(

switch (target->type) {
case ARG_PARSER_TYPE_BOOL:
return (strcmp(value, "1") == 0 || strcmp(value, "on") == 0)
|| (strcmp(value, "0") == 0 || strcmp(value, "off") == 0);
return ArgParser_ParseBool(value, NULL);
case ARG_PARSER_TYPE_INTEGER:
return ArgParser_ParseInteger(value, NULL);
case ARG_PARSER_TYPE_DECIMAL:
return ArgParser_ParseDecimal(value, NULL);
case ARG_PARSER_TYPE_STRING:
return ArgParser_ParseString(value, NULL, true);
}

case ARG_PARSER_TYPE_INT:
for (size_t i = 0; i < strlen(value); i++) {
if (!isdigit(value[i])) {
return false;
}
return false;
}

bool ArgParser_ParseBool(const char *const value, bool *const target)
{
if (strcmp(value, "0") == 0 || strcmp(value, "off") == 0) {
if (target != NULL) {
*target = false;
}
return true;
}

case ARG_PARSER_TYPE_FLOAT: {
bool has_dot = false;
for (size_t i = 0; i < strlen(value); i++) {
if (!isdigit(value[i])) {
if (value[i] == '.') {
if (has_dot) {
return false;
}
has_dot = true;
} else {
if (strcmp(value, "1") == 0 || strcmp(value, "on") == 0) {
if (target != NULL) {
*target = true;
}
return true;
}

return false;
}

bool ArgParser_ParseInteger(const char *const value, int32_t *const target)
{
for (size_t i = 0; i < strlen(value); i++) {
if (!isdigit(value[i])) {
return false;
}
}
if (target != NULL) {
*target = atoi(value);
}
return true;
}

bool ArgParser_ParseDecimal(const char *const value, float *const target)
{
bool has_dot = false;
for (size_t i = 0; i < strlen(value); i++) {
if (!isdigit(value[i])) {
if (value[i] == '.') {
if (has_dot) {
return false;
}
has_dot = true;
} else {
return false;
}
}
return true;
}

case ARG_PARSER_TYPE_STRING:
return true;
if (target != NULL) {
*target = atof(value);
}
return true;
}

return false;
bool ArgParser_ParseString(
const char *const value, char **const target, bool allow_empty)
{
if (!allow_empty && strcmp(value, "") == 0) {
return false;
}
if (target != NULL) {
*target = Memory_DupStr(value);
}
return true;
}

void ArgParser_Init(ARG_PARSER *const parser)
Expand All @@ -165,7 +206,7 @@ void ArgParser_Destroy(ARG_PARSER *const parser)
{
for (int32_t i = 0; i < parser->argc; i++) {
ARG_PARSER_ARGUMENT *const arg = &parser->args[i];
Memory_FreePointer(&arg->value.string_val);
Memory_FreePointer(&arg->value.val_string);
Memory_FreePointer(&arg->id);
Memory_FreePointer(&arg->short_name);
Memory_FreePointer(&arg->long_name);
Expand Down Expand Up @@ -193,10 +234,10 @@ void ArgParser_AddArgument(
arg->mandatory = user_arg->mandatory;

arg->provided = false;
arg->value.bool_val = false;
arg->value.string_val = NULL;
arg->value.int_val = 0;
arg->value.float_val = 0.0f;
arg->value.val_bool = false;
arg->value.val_string = NULL;
arg->value.val_integer = 0;
arg->value.val_decimal = 0.0f;
}

const ARG_PARSER_ARGUMENT *ArgParser_GetArgument(
Expand Down Expand Up @@ -239,7 +280,7 @@ bool ArgParser_ParseArgs(
|| (arg->long_name && strcmp(argv[i], arg->long_name) == 0)) {
matched = true;
if (arg->type == ARG_PARSER_TYPE_BOOL) {
arg->value.bool_val = true;
arg->value.val_bool = true;
} else {
if (++i >= argc) {
return false;
Expand Down

0 comments on commit 2688fd0

Please sign in to comment.