argpar.{c,h}: remove `ARGPAR_HIDDEN` from header file
[argpar.git] / argpar / argpar.h
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
5 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
6 */
7
8 #ifndef ARGPAR_ARGPAR_H
9 #define ARGPAR_ARGPAR_H
10
11 #include <stdbool.h>
12
13 #if defined(__cplusplus)
14 extern "C" {
15 #endif
16
17 /*!
18 @mainpage
19
20 See the \ref api module.
21
22 @addtogroup api argpar API
23 @{
24
25 argpar is a library which provides an iterator-based API to parse
26 command-line arguments.
27
28 The argpar parser supports:
29
30 <ul>
31 <li>
32 Short options without an argument, possibly tied together:
33
34 @code{.unparsed}
35 -f -auf -n
36 @endcode
37
38 <li>
39 Short options with arguments:
40
41 @code{.unparsed}
42 -b 45 -f/mein/file -xyzhello
43 @endcode
44
45 <li>
46 Long options without an argument:
47
48 @code{.unparsed}
49 --five-guys --burger-king --pizza-hut --subway
50 @endcode
51
52 <li>
53 Long options with arguments (two original arguments or a single
54 one with a <code>=</code> character):
55
56 @code{.unparsed}
57 --security enable --time=18.56
58 @endcode
59
60 <li>
61 Non-option arguments (anything else, including
62 <code>-</code> and <code>\--</code>).
63
64 A non-option argument cannot have the form of an option, for example
65 if you need to pass the exact relative path
66 <code>\--component</code>. In that case, you would need to pass
67 <code>./\--component</code>. There's no generic way to escape
68 <code>-</code> as of this version.
69 </ul>
70
71 Create a parsing iterator with argpar_iter_create(), then repeatedly
72 call argpar_iter_next() to access the parsing results (items), until one
73 of:
74
75 - There are no more arguments.
76
77 - The argument parser encounters an error (for example, an unknown
78 option).
79
80 - You need to stop.
81
82 argpar_iter_create() accepts duplicate option descriptors in
83 \p descrs (argpar_iter_next() produces one item for each
84 instance).
85
86 A parsing item (the result of argpar_iter_next()) has the type
87 #argpar_item.
88
89 Get the type (option or non-option) of an item with
90 \link argpar_item_type(const argpar_item_t *) argpar_item_type()\endlink.
91 Each item type has its set of dedicated functions
92 (\c argpar_item_opt_ and \c argpar_item_non_opt_ prefixes).
93
94 argpar_iter_next() produces the items in the same order that it parses
95 original arguments, including non-option arguments. This means, for
96 example, that for:
97
98 @code{.unparsed}
99 --hello --count=23 /path/to/file -ab --type file -- magie
100 @endcode
101
102 argpar_iter_next() produces the following items, in this order:
103
104 -# Option item: <code>\--hello</code>.
105 -# Option item: <code>\--count</code> with argument <code>23</code>.
106 -# Non-option item: <code>/path/to/file</code>.
107 -# Option item: <code>-a</code>.
108 -# Option item: <code>-b</code>.
109 -# Option item: <code>\--type</code> with argument <code>file</code>.
110 -# Non-option item: <code>\--</code>.
111 -# Non-option item: <code>magie</code>.
112 */
113
114 /* Internal: `noexcept` specifier if C++ ≥ 11 */
115 #if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
116 # define ARGPAR_NOEXCEPT noexcept
117 #else
118 # define ARGPAR_NOEXCEPT
119 #endif
120
121 typedef struct argpar_opt_descr argpar_opt_descr_t;
122
123 /*!
124 @name Item API
125 @{
126 */
127
128 /*!
129 @brief
130 Type of a parsing item, as returned by
131 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
132 */
133 typedef enum argpar_item_type {
134 /// Option
135 ARGPAR_ITEM_TYPE_OPT,
136
137 /// Non-option
138 ARGPAR_ITEM_TYPE_NON_OPT,
139 } argpar_item_type_t;
140
141 /*!
142 @struct argpar_item
143
144 @brief
145 Opaque parsing item type
146
147 argpar_iter_next() sets a pointer to such a type.
148 */
149 typedef struct argpar_item argpar_item_t;
150
151 /*!
152 @brief
153 Returns the type of the parsing item \p item.
154
155 @param[in] item
156 Parsing item of which to get the type.
157
158 @returns
159 Type of \p item.
160
161 @pre
162 \p item is not \c NULL.
163 */
164 argpar_item_type_t argpar_item_type(const argpar_item_t *item) ARGPAR_NOEXCEPT;
165
166 /*!
167 @brief
168 Returns the option descriptor of the option parsing item \p item.
169
170 @param[in] item
171 Option parsing item of which to get the option descriptor.
172
173 @returns
174 Option descriptor of \p item.
175
176 @pre
177 \p item is not \c NULL.
178 @pre
179 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
180 */
181 const argpar_opt_descr_t *argpar_item_opt_descr(
182 const argpar_item_t *item) ARGPAR_NOEXCEPT;
183
184 /*!
185 @brief
186 Returns the argument of the option parsing item \p item, or
187 \c NULL if none.
188
189 @param[in] item
190 Option parsing item of which to get the argument.
191
192 @returns
193 Argument of \p item, or \c NULL if none.
194
195 @pre
196 \p item is not \c NULL.
197 @pre
198 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
199 */
200 const char *argpar_item_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
201
202 /*!
203 @brief
204 Returns the complete original argument, pointing to one of the
205 entries of the original arguments (in \p argv, as passed to
206 argpar_iter_create()), of the non-option parsing item \p item.
207
208 @param[in] item
209 Non-option parsing item of which to get the complete original
210 argument.
211
212 @returns
213 Complete original argument of \p item.
214
215 @pre
216 \p item is not \c NULL.
217 @pre
218 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
219 */
220 const char *argpar_item_non_opt_arg(
221 const argpar_item_t *item) ARGPAR_NOEXCEPT;
222
223 /*!
224 @brief
225 Returns the index, within \em all the original arguments (in
226 \p argv, as passed to argpar_iter_create()), of the non-option
227 parsing item \p item.
228
229 For example, with the following command line (all options have no
230 argument):
231
232 @code{.unparsed}
233 -f -m meow --jus mix --kilo
234 @endcode
235
236 The original argument index of \c meow is&nbsp;2 while the original
237 argument index of \c mix is&nbsp;4.
238
239 @param[in] item
240 Non-option parsing item of which to get the original argument index.
241
242 @returns
243 Original argument index of \p item.
244
245 @pre
246 \p item is not \c NULL.
247 @pre
248 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
249
250 @sa
251 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
252 of a non-option parsing item.
253 */
254 unsigned int argpar_item_non_opt_orig_index(
255 const argpar_item_t *item) ARGPAR_NOEXCEPT;
256
257 /*!
258 @brief
259 Returns the index, within the parsed non-option parsing items, of
260 the non-option parsing item \p item.
261
262 For example, with the following command line (all options have no
263 argument):
264
265 @code{.unparsed}
266 -f -m meow --jus mix --kilo
267 @endcode
268
269 The non-option index of \c meow is&nbsp;0 while the original
270 argument index of \c mix is&nbsp;1.
271
272 @param[in] item
273 Non-option parsing item of which to get the non-option index.
274
275 @returns
276 Non-option index of \p item.
277
278 @pre
279 \p item is not \c NULL.
280 @pre
281 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
282
283 @sa
284 argpar_item_non_opt_orig_index() -- Returns the original argument
285 index of a non-option parsing item.
286 */
287 unsigned int argpar_item_non_opt_non_opt_index(
288 const argpar_item_t *item) ARGPAR_NOEXCEPT;
289
290 /*!
291 @brief
292 Destroys the parsing item \p item.
293
294 @param[in] item
295 Parsing item to destroy (may be \c NULL).
296 */
297 void argpar_item_destroy(const argpar_item_t *item) ARGPAR_NOEXCEPT;
298
299 /*!
300 @def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
301
302 @brief
303 Calls argpar_item_destroy() with \p _item, and then sets \p _item
304 to \c NULL.
305
306 @param[in] _item
307 Item to destroy and variable to reset
308 (<code>const argpar_item_t *</code> type).
309 */
310 #define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
311 { \
312 argpar_item_destroy(_item); \
313 _item = NULL; \
314 }
315
316 /// @}
317
318 /*!
319 @name Error API
320 @{
321 */
322
323 /*!
324 @brief
325 Parsing error type, as returned by
326 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
327 */
328 typedef enum argpar_error_type {
329 /// Unknown option error
330 ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
331
332 /// Missing option argument error
333 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
334
335 /// Unexpected option argument error
336 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
337 } argpar_error_type_t;
338
339 /*!
340 @struct argpar_error
341
342 @brief
343 Opaque parsing error type
344 */
345 typedef struct argpar_error argpar_error_t;
346
347 /*!
348 @brief
349 Returns the type of the parsing error object \p error.
350
351 @param[in] error
352 Parsing error of which to get the type.
353
354 @returns
355 Type of \p error.
356
357 @pre
358 \p error is not \c NULL.
359 */
360 argpar_error_type_t argpar_error_type(
361 const argpar_error_t *error) ARGPAR_NOEXCEPT;
362
363 /*!
364 @brief
365 Returns the index of the original argument (in \p argv, as passed to
366 argpar_iter_create()) for which the parsing error described by
367 \p error occurred.
368
369 @param[in] error
370 Parsing error of which to get the original argument index.
371
372 @returns
373 Original argument index of \p error.
374
375 @pre
376 \p error is not \c NULL.
377 */
378 unsigned int argpar_error_orig_index(
379 const argpar_error_t *error) ARGPAR_NOEXCEPT;
380
381 /*!
382 @brief
383 Returns the name of the unknown option for which the parsing error
384 described by \p error occurred.
385
386 The returned name includes any <code>-</code> or <code>\--</code>
387 prefix.
388
389 With the long option with argument form, for example
390 <code>\--mireille=deyglun</code>, this function only returns the name
391 part (<code>\--mireille</code> in the last example).
392
393 @param[in] error
394 Parsing error of which to get the name of the unknown option.
395
396 @returns
397 Name of the unknown option of \p error.
398
399 @pre
400 \p error is not \c NULL.
401 @pre
402 The type of \p error, as returned by
403 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
404 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
405 */
406 const char *argpar_error_unknown_opt_name(
407 const argpar_error_t *error) ARGPAR_NOEXCEPT;
408
409 /*!
410 @brief
411 Returns the descriptor of the option for which the parsing error
412 described by \p error occurred.
413
414 @param[in] error
415 Parsing error of which to get the option descriptor.
416 @param[out] is_short
417 @parblock
418 If not \c NULL, this function sets \p *is_short to:
419
420 - \c true if the option for which \p error occurred is a short
421 option.
422
423 - \c false if the option for which \p error occurred is a long
424 option.
425 @endparblock
426
427 @returns
428 Descriptor of the option of \p error.
429
430 @pre
431 \p error is not \c NULL.
432 @pre
433 The type of \p error, as returned by
434 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
435 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
436 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
437 */
438 const argpar_opt_descr_t *argpar_error_opt_descr(const argpar_error_t *error,
439 bool *is_short) ARGPAR_NOEXCEPT;
440
441 /*!
442 @brief
443 Destroys the parsing error \p error.
444
445 @param[in] error
446 Parsing error to destroy (may be \c NULL).
447 */
448 void argpar_error_destroy(const argpar_error_t *error) ARGPAR_NOEXCEPT;
449
450 /// @}
451
452 /*!
453 @name Iterator API
454 @{
455 */
456
457 /*!
458 @brief
459 Option descriptor
460
461 argpar_iter_create() accepts an array of instances of such a type,
462 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
463
464 The typical usage is, for example:
465
466 @code
467 const argpar_opt_descr_t descrs[] = {
468 { 0, 'd', NULL, false },
469 { 1, '\0', "squeeze", true },
470 { 2, 'm', "meow", true },
471 ARGPAR_OPT_DESCR_SENTINEL,
472 };
473 @endcode
474 */
475 typedef struct argpar_opt_descr {
476 /// Numeric ID, to uniquely identify this descriptor
477 const int id;
478
479 /// Short option character, or <code>'\0'</code>
480 const char short_name;
481
482 /// Long option name (without the <code>\--</code> prefix), or \c NULL
483 const char * const long_name;
484
485 /// \c true if this option has an argument
486 const bool with_arg;
487 } argpar_opt_descr_t;
488
489 /*!
490 @brief
491 Sentinel for an option descriptor array
492
493 The typical usage is, for example:
494
495 @code
496 const argpar_opt_descr_t descrs[] = {
497 { 0, 'd', NULL, false },
498 { 1, '\0', "squeeze", true },
499 { 2, 'm', "meow", true },
500 ARGPAR_OPT_DESCR_SENTINEL,
501 };
502 @endcode
503 */
504 #define ARGPAR_OPT_DESCR_SENTINEL { -1, '\0', NULL, false }
505
506 /*!
507 @struct argpar_iter
508
509 @brief
510 Opaque argpar iterator type
511
512 argpar_iter_create() returns a pointer to such a type.
513 */
514 typedef struct argpar_iter argpar_iter_t;
515
516 /*!
517 @brief
518 Creates and returns an argument parsing iterator to parse the
519 original arguments \p argv of which the count is \p argc using the
520 option descriptors \p descrs.
521
522 This function initializes the returned structure, but doesn't actually
523 start parsing the arguments.
524
525 argpar considers \em all the elements of \p argv, including the first
526 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
527 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
528 receives, or ignore the parsing item of the first call to
529 argpar_iter_next().
530
531 \p *argv and \p *descrs must \em not change for all of:
532
533 - The lifetime of the returned iterator (until you call
534 argpar_iter_destroy()).
535
536 - The lifetime of any parsing item (until you call
537 argpar_item_destroy()) which argpar_iter_next() creates from the
538 returned iterator.
539
540 - The lifetime of any parsing error (until you call
541 argpar_error_destroy()) which argpar_iter_next() creates from the
542 returned iterator.
543
544 @param[in] argc
545 Number of original arguments to parse in \p argv.
546 @param[in] argv
547 Original arguments to parse, of which the count is \p argc.
548 @param[in] descrs
549 @parblock
550 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
551
552 May contain duplicate entries.
553 @endparblock
554
555 @returns
556 New argument parsing iterator, or \c NULL on memory error.
557
558 @pre
559 \p argc is greater than 0.
560 @pre
561 \p argv is not \c NULL.
562 @pre
563 The first \p argc elements of \p argv are not \c NULL.
564 @pre
565 \p descrs is not \c NULL.
566
567 @sa
568 argpar_iter_destroy() -- Destroys an argument parsing iterator.
569 */
570 argpar_iter_t *argpar_iter_create(unsigned int argc, const char * const *argv,
571 const argpar_opt_descr_t *descrs) ARGPAR_NOEXCEPT;
572
573 /*!
574 @brief
575 Destroys the argument parsing iterator \p iter.
576
577 @param[in] iter
578 Argument parsing iterator to destroy (may be \c NULL).
579
580 @sa
581 argpar_iter_create() -- Creates an argument parsing iterator.
582 */
583 void argpar_iter_destroy(argpar_iter_t *iter) ARGPAR_NOEXCEPT;
584
585 /*!
586 @brief
587 Return type of argpar_iter_next().
588
589 Error status enumerators have a negative value.
590 */
591 typedef enum argpar_iter_next_status {
592 /// Success
593 ARGPAR_ITER_NEXT_STATUS_OK,
594
595 /// End of iteration (no more original arguments to parse)
596 ARGPAR_ITER_NEXT_STATUS_END,
597
598 /// Parsing error
599 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
600
601 /// Memory error
602 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
603 } argpar_iter_next_status_t;
604
605 /*!
606 @brief
607 Sets \p *item to the next item of the argument parsing iterator
608 \p iter and advances \p iter.
609
610 If there are no more original arguments to parse, this function returns
611 #ARGPAR_ITER_NEXT_STATUS_END.
612
613 @param[in] iter
614 Argument parsing iterator from which to get the next parsing item.
615 @param[out] item
616 @parblock
617 On success, \p *item is the next parsing item of \p iter.
618
619 Destroy \p *item with argpar_item_destroy().
620 @endparblock
621 @param[out] error
622 @parblock
623 When this function returns #ARGPAR_ITER_NEXT_STATUS_ERROR,
624 if this parameter is not \c NULL, \p *error contains details about
625 the error.
626
627 Destroy \p *error with argpar_error_destroy().
628 @endparblock
629
630 @returns
631 Status code.
632
633 @pre
634 \p iter is not \c NULL.
635 @pre
636 \p item is not \c NULL.
637 */
638 argpar_iter_next_status_t argpar_iter_next(argpar_iter_t *iter,
639 const argpar_item_t **item,
640 const argpar_error_t **error) ARGPAR_NOEXCEPT;
641
642 /*
643 * Returns the number of ingested elements from `argv`, as passed to
644 * argpar_iter_create() to create `*iter`, that were required to produce
645 * the previously returned items.
646 */
647
648 /*!
649 @brief
650 Returns the number of ingested original arguments (in
651 \p argv, as passed to argpar_iter_create() to create \p iter) that
652 the parser ingested to produce the \em previous parsing items.
653
654 @param[in] iter
655 Argument parsing iterator of which to get the number of ingested
656 original arguments.
657
658 @returns
659 Number of original arguments which \p iter ingested.
660
661 @pre
662 \p iter is not \c NULL.
663 */
664 unsigned int argpar_iter_ingested_orig_args(
665 const argpar_iter_t *iter) ARGPAR_NOEXCEPT;
666
667 /// @}
668
669 /// @}
670
671 #if defined(__cplusplus)
672 }
673 #endif
674
675 #endif /* ARGPAR_ARGPAR_H */
This page took 0.054353 seconds and 5 git commands to generate.