Skip to content
Snippets Groups Projects
Commit d82cd6ac authored by Andre Maroneze's avatar Andre Maroneze
Browse files

[kgflags] add new case study

parent ebd7b71f
No related branches found
No related tags found
No related merge requests found
#define KGFLAGS_IMPLEMENTATION
#include "../kgflags.h"
int main(int argc, char **argv) {
const char *string_val = NULL;
kgflags_string("string", "lorem", "String flag.", true, &string_val);
bool bool_val = false;
kgflags_bool("bool", false, "Boolean flag.", true, &bool_val);
int int_val = 0;
kgflags_int("int", 0, "Integer flag.", true, &int_val);
double double_val = 0;
kgflags_double("double", 0.0, "Double flag.", true, &double_val);
kgflags_string_array_t string_arr;
kgflags_string_array("string-array", "String array flag.", true, &string_arr);
kgflags_int_array_t int_arr;
kgflags_int_array("int-array", "Int array flag.", true, &int_arr);
kgflags_double_array_t double_arr;
kgflags_double_array("double-array", "Double array flag.", true, &double_arr);
kgflags_set_custom_description("Usage of fullapi [-FLAGS]:");
kgflags_set_prefix("-");
if (!kgflags_parse(argc, argv)) {
kgflags_print_errors();
kgflags_print_usage();
return 1;
}
printf("string_val: %s\n", string_val);
printf("bool_val: %s\n", bool_val ? "true" : "false");
printf("int_val: %d\n", int_val);
printf("double_val: %f\n", double_val);
printf("string-arr count: %d\n", kgflags_string_array_get_count(&string_arr));
for (int i = 0; i < kgflags_string_array_get_count(&string_arr); i++) {
printf("string-arr [%d]\n: %s", i, kgflags_string_array_get_item(&string_arr, i));
}
printf("int-arr count: %d\n", kgflags_int_array_get_count(&int_arr));
for (int i = 0; i < kgflags_int_array_get_count(&int_arr); i++) {
printf("int-arr [%d]: %d\n", i, kgflags_int_array_get_item(&int_arr, i));
}
printf("double-arr count: %d\n", kgflags_double_array_get_count(&double_arr));
for (int i = 0; i < kgflags_double_array_get_count(&double_arr); i++) {
printf("double-arr [%d]: %1.4g\n", i, kgflags_double_array_get_item(&double_arr, i));
}
int non_flag_count = kgflags_get_non_flag_args_count();
for (int i = 0; i < non_flag_count; i++) {
printf("Non-flag arguments [%d] = %s\n", i, kgflags_get_non_flag_arg(i));
}
return 0;
}
#define KGFLAGS_IMPLEMENTATION
#include "../kgflags.h"
int main(int argc, char **argv) {
const char *to_print = NULL; // guaranteed to be assigned only if kgflags_parse succeeds
kgflags_string("to-print", NULL, "String to print.", true, &to_print);
if (!kgflags_parse(argc, argv)) {
kgflags_print_errors();
kgflags_print_usage();
return 1;
}
puts(to_print);
return 0;
}
This diff is collapsed.
## About
kgflags is an easy to use command-line flag parsing library.
## Features
* Header-only (just copy kgflags.h).
* Easy to use.
* MIT licensed.
* No dynamic allocations.
* It supports strings, booleans, integers, double precision floats, string arrays, integer arrays, and double arrays.
* Not relying on macros and non-standard features which makes it easy to debug and modify.
* Test suites and examples.
## Example
```c
// simple.c
#define KGFLAGS_IMPLEMENTATION
#include "kgflags.h"
int main(int argc, char **argv) {
const char *to_print = NULL; // guaranteed to be assigned only if kgflags_parse succeeds
kgflags_string("to-print", NULL, "String to print.", true, &to_print);
if (!kgflags_parse(argc, argv)) {
kgflags_print_errors();
kgflags_print_usage();
return 1;
}
puts(to_print);
return 0;
}
```
```
$ gcc simple.c -o simple
$ ./simple --to-print "HELLO WORLD"
HELLO WORLD
```
More examples can be found in [examples directory](http://github.com/kgabis/kgflags/tree/master/examples).
## Installation
Run:
```
git clone https://github.com/kgabis/kgflags.git
```
and copy kgflags.h to you source code tree.
It behaves like most single header libraries - you have to declare KGFLAGS_IMPLEMENTATION in *one* C or C++ file *before* including it.
```c
#define KGFLAGS_IMPLEMENTATION
#include "kgflags.h"
```
You can also customize max number of supported arguments/flags/errors by redefining KGFLAGS_MAX_NON_FLAG_ARGS, KGFLAGS_MAX_FLAGS and KGFLAGS_MAX_ERRORS (*before* including kgflags.h).
## Testing
Run ```pushd tests; ./run_tests.sh; popd``` to compile and run tests.
## Limitations
* It relies on global variables which means it's not thread safe. This shouldn't be an issue since argument parsing is done only once during startup of the application.
* kgflags dosn't do any dynamic memory allocations. All string values returned are pointers to values given in argv array passed to ```kgflags_parse```. Same goes for default values, description strings and a prefix.
## Contributing
I will always merge *working* bug fixes. However, if you want to add something new to the API, please create an "issue" on github for this first so we can discuss if it should end up in the library before you start implementing it.
Remember to follow code's style and write appropriate tests.
## Acknowledgements
Many thanks to [Mateusz Belicki](https://github.com/mbelicki/) for all his suggestions and help.
kgflags is heavily inspired by Go's [flag package](https://golang.org/pkg/flag/).
## License
[The MIT License (MIT)](http://opensource.org/licenses/mit-license.php)
\ No newline at end of file
Unrecognized flag: -extra-flag
Unassigned required flag: -string
Unassigned required flag: -bool
Unassigned required flag: -int
Unassigned required flag: -double
Unassigned required flag: -string-array
Unassigned required flag: -int-array
Unassigned required flag: -double-array
Usage of fullapi [-FLAGS]:
Flags:
-string (string)
String flag.
-bool, -no-bool (boolean)
Boolean flag.
-int (integer)
Integer flag.
-double (float)
Double flag.
-string-array (array of strings)
String array flag.
-int-array (array of integers)
Int array flag.
-double-array (array of floats)
Double array flag.
#!/bin/bash
# set -xe
TESTS_OK=true
OUTDIR="output"
function compile_and_run {
COMPILER=$1
FLAGS=$2
CFILE="tests.c"
OUTPUT="tests"
echo "Compiling and running ${CFILE} with ${COMPILER} ${FLAGS}:"
touch "${OUTDIR}/${OUTPUT}"
${COMPILER} ${FLAGS} "${CFILE}" -o "${OUTDIR}/${OUTPUT}"
"./${OUTDIR}/${OUTPUT}" > "${OUTDIR}/output_${COMPILER}"
RES=$?
if [ ${RES} != "0" ]; then
echo " FAIL"
cat "${OUTDIR}/output_${COMPILER}"
TESTS_OK=false
else
echo " OK (output in ${OUTDIR}/output_${COMPILER})"
fi
}
if [ -d "${OUTDIR}" ]; then
rm -r "${OUTDIR}"
fi
mkdir "${OUTDIR}"
CC="gcc"
CFLAGS="-O0 -g -Wall -Wextra -std=c99 -pedantic-errors"
CPPC="g++"
CPPFLAGS="-O0 -g -Wall -Wextra -x c++ -Wno-c++11-compat-deprecated-writable-strings"
compile_and_run ${CC} "${CFLAGS}"
compile_and_run ${CPPC} "${CPPFLAGS}"
for f in `ls ../examples/*.c`
do
echo "Compiling ${f} with ${CC} ${CFLAGS}:"
fname=`basename ${f}`
${CC} ${CFLAGS} ${f} -o "${OUTDIR}/${fname}.out"
RES=$?
if [ ${RES} != "0" ]; then
echo " FAIL"
TESTS_OK=false
else
echo " OK"
fi
done
echo "Compiling, running and comparing output of ../examples/full_api.c with ${CC} ${CFLAGS}:"
${CC} ${CFLAGS} ../examples/full_api.c -o "${OUTDIR}/full_api"
"./${OUTDIR}/full_api" -extra-flag 2> "${OUTDIR}/full_api_output"
diff "${OUTDIR}/full_api_output" full_api_output
RES=$?
if [ ${RES} != "0" ]; then
echo " FAIL"
TESTS_OK=false
else
echo " OK"
fi
if [ "${TESTS_OK}" == true ]; then
echo "ALL TESTS SUCCEEDED"
else
echo "TESTS FAILED"
fi
This diff is collapsed.
#!/bin/bash
# set -xe
CC="gcc"
CFLAGS="-O0 -g -Wall -Wextra -std=c99 -pedantic-errors"
echo "Compiling, running and saving output of ../examples/full_api.c with ${CC} ${CFLAGS}"
${CC} ${CFLAGS} ../examples/full_api.c -o full_api
"./full_api" -extra-flag 2> "full_api_output"
rm full_api
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment