diff options
| author | Tyge Løvset <[email protected]> | 2020-12-09 20:44:58 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2020-12-09 20:44:58 +0100 |
| commit | 39cfd7c23e849b78d0156a3025c15a8eb25dd356 (patch) | |
| tree | 5725c1efbeceb0da4ff2262f27d5cc14b52ba6a7 | |
| parent | e3d6b9b3cb42a0fc066572e9aefb41b5cf45dc2c (diff) | |
| download | STC-modified-39cfd7c23e849b78d0156a3025c15a8eb25dd356.tar.gz STC-modified-39cfd7c23e849b78d0156a3025c15a8eb25dd356.zip | |
Renamed coption.h to copt.h. Added docs/copt_api.md.
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | docs/copt_api.md | 82 | ||||
| -rw-r--r-- | examples/ptr.c | 58 | ||||
| -rw-r--r-- | stc/copt.h (renamed from stc/coption.h) | 56 |
4 files changed, 148 insertions, 50 deletions
@@ -16,8 +16,8 @@ An elegant, fully typesafe, generic, customizable, user-friendly, consistent, an - [***cqueue*** - A **queue** adapter type](docs/cqueue_api.md)
- [***cpqueue*** - A **priority queue** adapter type](docs/cpqueue_api.md)
- [***cptr*** - Support for pointers and shared pointers in containers](docs/cptr_api.md)
+- [***copt*** - Implements *copt_get()*, a **getopt_long**-like function](docs/copt_api.md)
- [***crandom*** - A few very efficent modern **random number generators**](docs/crandom_api.md)
-- [***coption*** - Implements *coption_get()*, a **getopt_long**-like function](docs/coption_api.md)
- [***ccommon*** - Collection of general definitions](docs/ccommon_api.md)
The usage of the containers is quite similar to the C++ standard containers, so it should be easy if you are familiar with them.
diff --git a/docs/copt_api.md b/docs/copt_api.md new file mode 100644 index 00000000..e91c21ea --- /dev/null +++ b/docs/copt_api.md @@ -0,0 +1,82 @@ +# Introduction + +This describes the API of string type *copt_get()* function for command line argument parsing. + +## Types + +```c +enum { + copt_no_argument = 0, + copt_required_argument = 1, + copt_optional_argument = 2 +}; +typedef struct { + int ind; /* equivalent to optind */ + int opt; /* equivalent to optopt */ + const char *arg; /* equivalent to optarg */ + const char *faulty; /* points to the faulty option, if any */ + int longindex; /* index of long option; or -1 if short */ + ... +} copt_t; + +typedef struct { + const char *name; + int has_arg; + int val; +} copt_long_t; +``` + +## Methods + +``` +copt_t copt_init(void); +int copt_get(copt_t *opt, int argc, char *argv[], + const char *shortopts, const copt_long_t *longopts); +``` + +## Example + +``` +#include <stdio.h> +#include "stc/copt.h" + +int main(int argc, char *argv[]) { + static copt_long_t long_options[] = { + {"verbose", copt_no_argument, 'V'}, + {"help", copt_no_argument, 'H'}, + {"add", copt_no_argument, 'a'}, + {"append", copt_no_argument, 'b'}, + {"delete", copt_required_argument, 'd'}, + {"create", copt_required_argument, 'c'}, + {"file", copt_required_argument, 'f'}, + {NULL} + }; + copt_t opt = copt_inits; + int c; + while ((c = copt_get(&opt, argc, argv, ":if:lr", long_options)) != -1) { + switch (c) { + case 'V': case 'H': + case 'a': case 'b': + case 'd': case 'c': + case 'i': case 'l': + case 'r': + printf("option: %c\n", c); + break; + case 'f': + printf("filename: %s\n", opt.arg); + break; + case ':': + printf("option %s needs a value\n", opt.faulty); + break; + case '?': + printf("unknown option: %s\n", opt.faulty); + break; + } + } + + for (; opt.ind < argc; ++opt.ind) { + printf("extra arguments: %s\n", argv[opt.ind]); + } + return 0; +} +```
\ No newline at end of file diff --git a/examples/ptr.c b/examples/ptr.c index 4e8f11aa..8b3d9786 100644 --- a/examples/ptr.c +++ b/examples/ptr.c @@ -18,33 +18,51 @@ int Person_compare(const Person* p, const Person* q) { }
using_cvec(pe, Person, Person_del, Person_compare);
-using_cuptr(pe, Person, Person_del, Person_compare);
-using_cvec(pp, Person*, cuptr_pe_del, cuptr_pe_compare);
+
+using_cuptr(pu, Person, Person_del, Person_compare);
+using_cvec(pu, Person*, cuptr_pu_del, cuptr_pu_compare);
+
+using_csptr(ps, Person, Person_del, Person_compare);
+using_cvec(ps, csptr_ps, csptr_ps_del, csptr_ps_compare);
+
+
+const char* names[] = {
+ "Joe", "Jordan",
+ "Annie", "Aniston",
+ "Jane", "Jacobs"
+};
int main() {
- puts("Vec of Person *:");
- cvec_pp pvec = cvec_pp_init();
- cvec_pp_push_back(&pvec, Person_make(c_new(Person), "Joe", "Jordan"));
- cvec_pp_push_back(&pvec, Person_make(c_new(Person), "Annie", "Aniston"));
- cvec_pp_push_back(&pvec, Person_make(c_new(Person), "Jane", "Jacobs"));
-
- cvec_pp_sort(&pvec);
- c_foreach (i, cvec_pp, pvec)
- printf("%s %s\n", (*i.val)->name.str, (*i.val)->last.str);
-
- puts("\nVec of Person:");
- cvec_pe vec = cvec_pe_init();
Person tmp;
- cvec_pe_push_back(&vec, *Person_make(&tmp, "Joe", "Jordan"));
- cvec_pe_push_back(&vec, *Person_make(&tmp, "Annie", "Aniston"));
- cvec_pe_push_back(&vec, *Person_make(&tmp, "Jane", "Jacobs"));
-
+ cvec_pe vec = cvec_inits;
+ for (int i=0;i<6; i+=2) cvec_pe_push_back(&vec, *Person_make(&tmp, names[i], names[i+1]));
+ puts("cvec of Person:");
cvec_pe_sort(&vec);
c_foreach (i, cvec_pe, vec)
- printf("%s %s\n", i.val->name.str, i.val->last.str);
+ printf(" %s %s\n", i.val->name.str, i.val->last.str);
+
+ cvec_pu uvec = cvec_inits;
+ for (int i=0;i<6; i+=2) cvec_pu_push_back(&uvec, Person_make(c_new(Person), names[i], names[i+1]));
+ puts("cvec of cuptr<Person>:");
+ cvec_pu_sort(&uvec);
+ c_foreach (i, cvec_pu, uvec)
+ printf(" %s %s\n", (*i.val)->name.str, (*i.val)->last.str);
+
+ cvec_ps svec = cvec_inits;
+ for (int i=0;i<6; i+=2) cvec_ps_push_back(&svec, csptr_ps_from(Person_make(c_new(Person), names[i], names[i+1])));
+ puts("cvec of csptr<Person>:");
+ cvec_ps_sort(&svec);
+ c_foreach (i, cvec_ps, svec)
+ printf(" %s %s\n", (*i.val).get->name.str, (*i.val).get->last.str);
+
+ csptr_ps x = csptr_ps_share(svec.data[1]);
+ puts("\nDestroy svec:");
+ cvec_ps_del(&svec);
puts("\nDestroy pvec:");
- cvec_pp_del(&pvec);
+ cvec_pu_del(&uvec);
puts("\nDestroy vec:");
cvec_pe_del(&vec);
+ puts("\nDestroy x:");
+ csptr_ps_del(&x);
}
\ No newline at end of file diff --git a/stc/coption.h b/stc/copt.h index 9021909c..cc8ae826 100644 --- a/stc/coption.h +++ b/stc/copt.h @@ -20,34 +20,34 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifndef COPTIONS__H__
-#define COPTIONS__H__
+#ifndef COPT__H__
+#define COPT__H__
/*
// Inspired by https://attractivechaos.wordpress.com/2018/08/31/a-survey-of-argument-parsing-libraries-in-c-c
// Fixed major bugs with option arguments (both long and short).
// Added arg->faulty output field, and has a more consistent API.
//
-// coption_get() is similar to GNU's getopt_long(). Each call parses one option and
+// copt_get() is similar to GNU's getopt_long(). Each call parses one option and
// returns the option name. opt->arg points to the option argument if present.
// The function returns -1 when all command-line arguments are parsed. In this case,
// opt->ind is the index of the first non-option argument.
#include <stdio.h>
-#include <stc/coption.h>
+#include <stc/copt.h>
int main(int argc, char *argv[])
{
- coption_long_t longopts[] = {
- {"foo", coption_no_argument, 'f'},
- {"bar", coption_required_argument, 'b'},
- {"opt", coption_optional_argument, 'o'},
+ copt_long_t longopts[] = {
+ {"foo", copt_no_argument, 'f'},
+ {"bar", copt_required_argument, 'b'},
+ {"opt", copt_optional_argument, 'o'},
{NULL}
};
const char* optstr = "xy:z::123";
printf("program -x -y ARG -z [ARG] -1 -2 -3 --foo --bar ARG --opt [ARG] [ARGUMENTS]\n");
int c;
- coption_t opt = coption_init();
- while ((c = coption_get(&opt, argc, argv, optstr, longopts)) != -1) {
+ copt_t opt = copt_init();
+ while ((c = copt_get(&opt, argc, argv, optstr, longopts)) != -1) {
switch (c) {
case '?': printf("error: unknown option: %s\n", opt.faulty); break;
case ':': printf("error: missing argument for %s\n", opt.faulty); break;
@@ -65,9 +65,9 @@ int main(int argc, char *argv[]) #include <stdbool.h>
enum {
- coption_no_argument = 0,
- coption_required_argument = 1,
- coption_optional_argument = 2
+ copt_no_argument = 0,
+ copt_required_argument = 1,
+ copt_optional_argument = 2
};
typedef struct {
int ind; /* equivalent to optind */
@@ -77,20 +77,18 @@ typedef struct { int longindex; /* idx of long option; or -1 if short */
int _i, _pos, _nargs;
char _faulty[4];
-} coption_t;
+} copt_t;
typedef struct {
const char *name;
int has_arg;
int val;
-} coption_long_t;
+} copt_long_t;
-static inline coption_t coption_init(void) {
- const coption_t init = {1, 0, NULL, NULL, -1, 1, 0, 0, {'-', '?', '\0'}};
- return init;
-}
+static const copt_t copt_inits = {1, 0, NULL, NULL, -1, 1, 0, 0, {'-', '?', '\0'}};
+static inline copt_t copt_init(void) { return copt_inits; }
-static void _coption_permute(char *argv[], int j, int n) { /* move argv[j] over n elements to the left */
+static void _copt_permute(char *argv[], int j, int n) { /* move argv[j] over n elements to the left */
int k;
char *p = argv[j];
for (k = 0; k < n; ++k)
@@ -98,13 +96,13 @@ static void _coption_permute(char *argv[], int j, int n) { /* move argv[j] over argv[j - k] = p;
}
-/* @param opt output; must be initialized to coption_init() on first call
+/* @param opt output; must be initialized to copt_init() on first call
* @return ASCII val for a short option; longopt.val for a long option;
* -1 if argv[] is fully processed; '?' for an unknown option or
* an ambiguous long option; ':' if an option argument is missing
*/
-static int coption_get(coption_t *opt, int argc, char *argv[],
- const char *shortopts, const coption_long_t *longopts) {
+static int copt_get(copt_t *opt, int argc, char *argv[],
+ const char *shortopts, const copt_long_t *longopts) {
int optc = -1, i0, j, posixly_correct = (shortopts[0] == '+');
if (!posixly_correct) {
while (opt->_i < argc && (argv[opt->_i][0] != '-' || argv[opt->_i][1] == '\0'))
@@ -117,14 +115,14 @@ static int coption_get(coption_t *opt, int argc, char *argv[], }
if (argv[opt->_i][0] == '-' && argv[opt->_i][1] == '-') { /* "--" or a long option */
if (argv[opt->_i][2] == '\0') { /* a bare "--" */
- _coption_permute(argv, opt->_i, opt->_nargs);
+ _copt_permute(argv, opt->_i, opt->_nargs);
++opt->_i, opt->ind = opt->_i - opt->_nargs;
return -1;
}
opt->opt = 0, optc = '?', opt->_pos = -1;
if (longopts) { /* parse long options */
int k, n_exact = 0, n_partial = 0;
- const coption_long_t *o = 0, *o_exact = 0, *o_partial = 0;
+ const copt_long_t *o = 0, *o_exact = 0, *o_partial = 0;
for (j = 2; argv[opt->_i][j] != '\0' && argv[opt->_i][j] != '='; ++j) {} /* find the end of the option name */
for (k = 0; longopts[k].name != 0; ++k)
if (strncmp(&argv[opt->_i][2], longopts[k].name, j - 2) == 0) {
@@ -136,13 +134,13 @@ static int coption_get(coption_t *opt, int argc, char *argv[], o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0;
if (o) {
opt->opt = optc = o->val, opt->longindex = o - longopts;
- if (o->has_arg != coption_no_argument) {
+ if (o->has_arg != copt_no_argument) {
if (argv[opt->_i][j] == '=')
opt->arg = &argv[opt->_i][j + 1];
- else if (argv[opt->_i][j] == '\0' && opt->_i < argc - 1 && (o->has_arg == coption_required_argument ||
+ else if (argv[opt->_i][j] == '\0' && opt->_i < argc - 1 && (o->has_arg == copt_required_argument ||
argv[opt->_i + 1][0] != '-'))
opt->arg = argv[++opt->_i];
- else if (o->has_arg == coption_required_argument)
+ else if (o->has_arg == copt_required_argument)
optc = ':'; /* missing option argument */
}
}
@@ -169,7 +167,7 @@ static int coption_get(coption_t *opt, int argc, char *argv[], ++opt->_i, opt->_pos = 0;
if (opt->_nargs > 0) /* permute */
for (j = i0; j < opt->_i; ++j)
- _coption_permute(argv, j, opt->_nargs);
+ _copt_permute(argv, j, opt->_nargs);
}
opt->ind = opt->_i - opt->_nargs;
return optc;
|
