argpar.h: make all the functions `noexcept` with C++ ≥ 11
[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 struct argpar_item *) 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 /*
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".
117 *
118 * On Windows, symbols are local unless explicitly exported; see
119 * <https://gcc.gnu.org/wiki/Visibility>.
120 */
121 #if defined(_WIN32) || defined(__CYGWIN__)
122 # define ARGPAR_HIDDEN
123 #else
124 # define ARGPAR_HIDDEN __attribute__((visibility("hidden")))
125 #endif
126
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
134 struct argpar_opt_descr;
135
136 /*!
137 @name Item API
138 @{
139 */
140
141 /*!
142 @brief
143 Type of a parsing item, as returned by
144 \link argpar_item_type(const struct argpar_item *) argpar_item_type()\endlink.
145 */
146 enum argpar_item_type {
147 /// Option
148 ARGPAR_ITEM_TYPE_OPT,
149
150 /// Non-option
151 ARGPAR_ITEM_TYPE_NON_OPT,
152 };
153
154 /*!
155 @struct argpar_item
156
157 @brief
158 Opaque parsing item type
159
160 argpar_iter_next() sets a pointer to such a type.
161 */
162 struct argpar_item;
163
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
178 ARGPAR_HIDDEN
179 /// @endcond
180 enum argpar_item_type argpar_item_type(
181 const struct argpar_item *item) ARGPAR_NOEXCEPT;
182
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
199 ARGPAR_HIDDEN
200 /// @endcond
201 const struct argpar_opt_descr *argpar_item_opt_descr(
202 const struct argpar_item *item) ARGPAR_NOEXCEPT;
203
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
221 ARGPAR_HIDDEN
222 /// @endcond
223 const char *argpar_item_opt_arg(const struct argpar_item *item) ARGPAR_NOEXCEPT;
224
225 /*!
226 @brief
227 Returns the complete original argument, pointing to one of the
228 entries of the original arguments (in \p argv, as passed to
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
244 ARGPAR_HIDDEN
245 /// @endcond
246 const char *argpar_item_non_opt_arg(
247 const struct argpar_item *item) ARGPAR_NOEXCEPT;
248
249 /*!
250 @brief
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.
254
255 For example, with the following command line (all options have no
256 argument):
257
258 @code{.unparsed}
259 -f -m meow --jus mix --kilo
260 @endcode
261
262 The original argument index of \c meow is&nbsp;2 while the original
263 argument 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
281 ARGPAR_HIDDEN
282 /// @endcond
283 unsigned int argpar_item_non_opt_orig_index(
284 const struct argpar_item *item) ARGPAR_NOEXCEPT;
285
286 /*!
287 @brief
288 Returns the index, within the parsed non-option parsing items, of
289 the non-option parsing item \p item.
290
291 For example, with the following command line (all options have no
292 argument):
293
294 @code{.unparsed}
295 -f -m meow --jus mix --kilo
296 @endcode
297
298 The non-option index of \c meow is&nbsp;0 while the original
299 argument 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
317 ARGPAR_HIDDEN
318 /// @endcond
319 unsigned int argpar_item_non_opt_non_opt_index(
320 const struct argpar_item *item) ARGPAR_NOEXCEPT;
321
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
330 ARGPAR_HIDDEN
331 /// @endcond
332 void argpar_item_destroy(const struct argpar_item *item) ARGPAR_NOEXCEPT;
333
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
353 /*!
354 @name Error API
355 @{
356 */
357
358 /*!
359 @brief
360 Parsing error type, as returned by
361 \link argpar_error_type(const struct argpar_error *) argpar_error_type()\endlink.
362 */
363 enum 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
374 /*!
375 @struct argpar_error
376
377 @brief
378 Opaque parsing error type
379 */
380 struct argpar_error;
381
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
396 ARGPAR_HIDDEN
397 /// @endcond
398 enum argpar_error_type argpar_error_type(
399 const struct argpar_error *error) ARGPAR_NOEXCEPT;
400
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
417 ARGPAR_HIDDEN
418 /// @endcond
419 unsigned int argpar_error_orig_index(
420 const struct argpar_error *error) ARGPAR_NOEXCEPT;
421
422 /*!
423 @brief
424 Returns the name of the unknown option for which the parsing error
425 described by \p error occurred.
426
427 The returned name includes any <code>-</code> or <code>\--</code>
428 prefix.
429
430 With the long option with argument form, for example
431 <code>\--mireille=deyglun</code>, this function only returns the name
432 part (<code>\--mireille</code> in the last example).
433
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
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.
446 */
447 /// @cond hidden_macro
448 ARGPAR_HIDDEN
449 /// @endcond
450 const char *argpar_error_unknown_opt_name(
451 const struct argpar_error *error) ARGPAR_NOEXCEPT;
452
453 /*!
454 @brief
455 Returns the descriptor of the option for which the parsing error
456 described by \p error occurred.
457
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
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.
481 */
482 /// @cond hidden_macro
483 ARGPAR_HIDDEN
484 /// @endcond
485 const struct argpar_opt_descr *argpar_error_opt_descr(
486 const struct argpar_error *error,
487 bool *is_short) ARGPAR_NOEXCEPT;
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
497 ARGPAR_HIDDEN
498 /// @endcond
499 void argpar_error_destroy(const struct argpar_error *error) ARGPAR_NOEXCEPT;
500
501 /// @}
502
503 /*!
504 @name Iterator API
505 @{
506 */
507
508 /*!
509 @brief
510 Option descriptor
511
512 argpar_iter_create() accepts an array of instances of such a type,
513 terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
514
515 The typical usage is, for example:
516
517 @code
518 const 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 */
526 struct 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
544 The typical usage is, for example:
545
546 @code
547 const 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
563 argpar_iter_create() returns a pointer to such a type.
564 */
565 struct 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
573 This function initializes the returned structure, but doesn't actually
574 start parsing the arguments.
575
576 argpar considers \em all the elements of \p argv, including the first
577 one, so that you would typically pass <code>(argc - 1)</code> as \p argc
578 and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
579 receives, or ignore the parsing item of the first call to
580 argpar_iter_next().
581
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.
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
622 ARGPAR_HIDDEN
623 /// @endcond
624 struct argpar_iter *argpar_iter_create(unsigned int argc,
625 const char * const *argv,
626 const struct argpar_opt_descr *descrs) ARGPAR_NOEXCEPT;
627
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
639 ARGPAR_HIDDEN
640 /// @endcond
641 void argpar_iter_destroy(struct argpar_iter *iter) ARGPAR_NOEXCEPT;
642
643 /*!
644 @brief
645 Return type of argpar_iter_next().
646
647 Error status enumerators have a negative value.
648 */
649 enum argpar_iter_next_status {
650 /// Success
651 ARGPAR_ITER_NEXT_STATUS_OK,
652
653 /// End of iteration (no more original arguments to parse)
654 ARGPAR_ITER_NEXT_STATUS_END,
655
656 /// Parsing error
657 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
658
659 /// Memory error
660 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
661 };
662
663 /*!
664 @brief
665 Sets \p *item to the next item of the argument parsing iterator
666 \p iter and advances \p iter.
667
668 If 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
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.
684
685 Destroy \p *error with argpar_error_destroy().
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
697 ARGPAR_HIDDEN
698 /// @endcond
699 enum argpar_iter_next_status argpar_iter_next(
700 struct argpar_iter *iter, const struct argpar_item **item,
701 const struct argpar_error **error) ARGPAR_NOEXCEPT;
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 */
708
709 /*!
710 @brief
711 Returns the number of ingested original arguments (in
712 \p argv, as passed to argpar_iter_create() to create \p iter) that
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
726 ARGPAR_HIDDEN
727 /// @endcond
728 unsigned int argpar_iter_ingested_orig_args(
729 const struct argpar_iter *iter) ARGPAR_NOEXCEPT;
730
731 /// @}
732
733 /// @}
734
735 #if defined(__cplusplus)
736 }
737 #endif
738
739 #endif /* ARGPAR_ARGPAR_H */
This page took 0.052606 seconds and 5 git commands to generate.