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