summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2020-12-09 20:44:58 +0100
committerTyge Løvset <[email protected]>2020-12-09 20:44:58 +0100
commit39cfd7c23e849b78d0156a3025c15a8eb25dd356 (patch)
tree5725c1efbeceb0da4ff2262f27d5cc14b52ba6a7
parente3d6b9b3cb42a0fc066572e9aefb41b5cf45dc2c (diff)
downloadSTC-modified-39cfd7c23e849b78d0156a3025c15a8eb25dd356.tar.gz
STC-modified-39cfd7c23e849b78d0156a3025c15a8eb25dd356.zip
Renamed coption.h to copt.h. Added docs/copt_api.md.
-rw-r--r--README.md2
-rw-r--r--docs/copt_api.md82
-rw-r--r--examples/ptr.c58
-rw-r--r--stc/copt.h (renamed from stc/coption.h)56
4 files changed, 148 insertions, 50 deletions
diff --git a/README.md b/README.md
index e012e450..e2614973 100644
--- a/README.md
+++ b/README.md
@@ -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;