Add clang-tidy configuration file
[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
7554f0b6 90\link argpar_item_type(const argpar_item_t *) argpar_item_type()\endlink.
1c881812 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
9b49cc18
PP
114/* Internal: `noexcept` specifier if C++ ≥ 11 */
115#if defined(__cplusplus) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
45ad74d3 116# define ARGPAR_NOEXCEPT noexcept
9b49cc18 117#else
45ad74d3 118# define ARGPAR_NOEXCEPT
9b49cc18
PP
119#endif
120
7554f0b6 121typedef struct argpar_opt_descr argpar_opt_descr_t;
903a5b8a 122
9e2c879b
PP
123/*!
124@name Item API
125@{
126*/
903a5b8a 127
9e2c879b
PP
128/*!
129@brief
1c881812 130 Type of a parsing item, as returned by
7554f0b6 131 \link argpar_item_type(const argpar_item *) argpar_item_type()\endlink.
9e2c879b 132*/
45ad74d3
SM
133typedef enum argpar_item_type
134{
135 /// Option
136 ARGPAR_ITEM_TYPE_OPT,
903a5b8a 137
45ad74d3
SM
138 /// Non-option
139 ARGPAR_ITEM_TYPE_NON_OPT,
7554f0b6 140} argpar_item_type_t;
903a5b8a 141
9e2c879b
PP
142/*!
143@struct argpar_item
144
145@brief
146 Opaque parsing item type
147
148argpar_iter_next() sets a pointer to such a type.
149*/
7554f0b6 150typedef struct argpar_item argpar_item_t;
903a5b8a 151
9e2c879b
PP
152/*!
153@brief
154 Returns the type of the parsing item \p item.
155
156@param[in] item
157 Parsing item of which to get the type.
158
159@returns
160 Type of \p item.
161
162@pre
163 \p item is not \c NULL.
164*/
7554f0b6 165argpar_item_type_t argpar_item_type(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 166
9e2c879b
PP
167/*!
168@brief
169 Returns the option descriptor of the option parsing item \p item.
170
171@param[in] item
172 Option parsing item of which to get the option descriptor.
173
174@returns
175 Option descriptor of \p item.
176
177@pre
178 \p item is not \c NULL.
179@pre
180 \p item has the type #ARGPAR_ITEM_TYPE_OPT.
181*/
45ad74d3 182const argpar_opt_descr_t *argpar_item_opt_descr(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 183
9e2c879b
PP
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*/
7554f0b6 200const char *argpar_item_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 201
9e2c879b
PP
202/*!
203@brief
204 Returns the complete original argument, pointing to one of the
8b95d883 205 entries of the original arguments (in \p argv, as passed to
9e2c879b
PP
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*/
45ad74d3 220const char *argpar_item_non_opt_arg(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 221
9e2c879b
PP
222/*!
223@brief
8b95d883
PP
224 Returns the index, within \em all the original arguments (in
225 \p argv, as passed to argpar_iter_create()), of the non-option
226 parsing item \p item.
9e2c879b
PP
227
228For example, with the following command line (all options have no
229argument):
230
231@code{.unparsed}
232-f -m meow --jus mix --kilo
233@endcode
234
235The original argument index of \c meow is&nbsp;2 while the original
236argument index of \c mix is&nbsp;4.
237
238@param[in] item
239 Non-option parsing item of which to get the original argument index.
240
241@returns
242 Original argument index of \p item.
243
244@pre
245 \p item is not \c NULL.
246@pre
247 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
248
249@sa
250 argpar_item_non_opt_non_opt_index() -- Returns the non-option index
251 of a non-option parsing item.
252*/
45ad74d3 253unsigned int argpar_item_non_opt_orig_index(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 254
9e2c879b
PP
255/*!
256@brief
257 Returns the index, within the parsed non-option parsing items, of
258 the non-option parsing item \p item.
259
260For example, with the following command line (all options have no
261argument):
262
263@code{.unparsed}
264-f -m meow --jus mix --kilo
265@endcode
266
267The non-option index of \c meow is&nbsp;0 while the original
268argument index of \c mix is&nbsp;1.
269
270@param[in] item
271 Non-option parsing item of which to get the non-option index.
272
273@returns
274 Non-option index of \p item.
275
276@pre
277 \p item is not \c NULL.
278@pre
279 \p item has the type #ARGPAR_ITEM_TYPE_NON_OPT.
280
281@sa
282 argpar_item_non_opt_orig_index() -- Returns the original argument
283 index of a non-option parsing item.
284*/
45ad74d3 285unsigned int argpar_item_non_opt_non_opt_index(const argpar_item_t *item) ARGPAR_NOEXCEPT;
903a5b8a 286
9e2c879b
PP
287/*!
288@brief
289 Destroys the parsing item \p item.
290
291@param[in] item
292 Parsing item to destroy (may be \c NULL).
293*/
7554f0b6 294void argpar_item_destroy(const argpar_item_t *item) ARGPAR_NOEXCEPT;
a473f6cb 295
9e2c879b
PP
296/*!
297@def ARGPAR_ITEM_DESTROY_AND_RESET(_item)
298
299@brief
300 Calls argpar_item_destroy() with \p _item, and then sets \p _item
301 to \c NULL.
302
303@param[in] _item
304 Item to destroy and variable to reset
7554f0b6 305 (<code>const argpar_item_t *</code> type).
9e2c879b 306*/
45ad74d3
SM
307#define ARGPAR_ITEM_DESTROY_AND_RESET(_item) \
308 { \
309 argpar_item_destroy(_item); \
310 _item = NULL; \
311 }
9e2c879b
PP
312
313/// @}
314
8b95d883
PP
315/*!
316@name Error API
317@{
318*/
319
1c881812
PP
320/*!
321@brief
322 Parsing error type, as returned by
7554f0b6 323 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink.
1c881812 324*/
45ad74d3
SM
325typedef enum argpar_error_type
326{
327 /// Unknown option error
328 ARGPAR_ERROR_TYPE_UNKNOWN_OPT,
10aefab2 329
45ad74d3
SM
330 /// Missing option argument error
331 ARGPAR_ERROR_TYPE_MISSING_OPT_ARG,
10aefab2 332
45ad74d3
SM
333 /// Unexpected option argument error
334 ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG,
7554f0b6 335} argpar_error_type_t;
10aefab2 336
8b95d883
PP
337/*!
338@struct argpar_error
339
340@brief
341 Opaque parsing error type
342*/
7554f0b6 343typedef struct argpar_error argpar_error_t;
8b95d883 344
1c881812
PP
345/*!
346@brief
347 Returns the type of the parsing error object \p error.
348
349@param[in] error
350 Parsing error of which to get the type.
351
352@returns
353 Type of \p error.
354
355@pre
356 \p error is not \c NULL.
357*/
45ad74d3 358argpar_error_type_t argpar_error_type(const argpar_error_t *error) ARGPAR_NOEXCEPT;
10aefab2 359
8b95d883
PP
360/*!
361@brief
362 Returns the index of the original argument (in \p argv, as passed to
363 argpar_iter_create()) for which the parsing error described by
364 \p error occurred.
365
366@param[in] error
367 Parsing error of which to get the original argument index.
368
369@returns
370 Original argument index of \p error.
371
372@pre
373 \p error is not \c NULL.
374*/
45ad74d3 375unsigned int argpar_error_orig_index(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
376
377/*!
378@brief
379 Returns the name of the unknown option for which the parsing error
380 described by \p error occurred.
381
382The returned name includes any <code>-</code> or <code>\--</code>
383prefix.
384
385With the long option with argument form, for example
386<code>\--mireille=deyglun</code>, this function only returns the name
387part (<code>\--mireille</code> in the last example).
388
8b95d883
PP
389@param[in] error
390 Parsing error of which to get the name of the unknown option.
391
392@returns
393 Name of the unknown option of \p error.
394
395@pre
396 \p error is not \c NULL.
397@pre
1c881812 398 The type of \p error, as returned by
7554f0b6 399 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
1c881812 400 is #ARGPAR_ERROR_TYPE_UNKNOWN_OPT.
8b95d883 401*/
45ad74d3 402const char *argpar_error_unknown_opt_name(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
403
404/*!
405@brief
406 Returns the descriptor of the option for which the parsing error
407 described by \p error occurred.
408
8b95d883
PP
409@param[in] error
410 Parsing error of which to get the option descriptor.
411@param[out] is_short
412 @parblock
413 If not \c NULL, this function sets \p *is_short to:
414
415 - \c true if the option for which \p error occurred is a short
416 option.
417
418 - \c false if the option for which \p error occurred is a long
419 option.
420 @endparblock
421
422@returns
423 Descriptor of the option of \p error.
424
425@pre
426 \p error is not \c NULL.
427@pre
1c881812 428 The type of \p error, as returned by
7554f0b6 429 \link argpar_error_type(const argpar_error_t *) argpar_error_type()\endlink,
1c881812
PP
430 is #ARGPAR_ERROR_TYPE_MISSING_OPT_ARG or
431 #ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG.
8b95d883 432*/
7554f0b6 433const argpar_opt_descr_t *argpar_error_opt_descr(const argpar_error_t *error,
45ad74d3 434 bool *is_short) ARGPAR_NOEXCEPT;
8b95d883
PP
435
436/*!
437@brief
438 Destroys the parsing error \p error.
439
440@param[in] error
441 Parsing error to destroy (may be \c NULL).
442*/
7554f0b6 443void argpar_error_destroy(const argpar_error_t *error) ARGPAR_NOEXCEPT;
8b95d883
PP
444
445/// @}
446
9e2c879b
PP
447/*!
448@name Iterator API
449@{
450*/
451
452/*!
453@brief
454 Option descriptor
455
456argpar_iter_create() accepts an array of instances of such a type,
457terminated with #ARGPAR_OPT_DESCR_SENTINEL, as its \p descrs parameter.
458
459The typical usage is, for example:
460
461@code
7554f0b6 462const argpar_opt_descr_t descrs[] = {
9e2c879b
PP
463 { 0, 'd', NULL, false },
464 { 1, '\0', "squeeze", true },
465 { 2, 'm', "meow", true },
466 ARGPAR_OPT_DESCR_SENTINEL,
467};
468@endcode
469*/
45ad74d3
SM
470typedef struct argpar_opt_descr
471{
472 /// Numeric ID, to uniquely identify this descriptor
473 const int id;
9e2c879b 474
45ad74d3
SM
475 /// Short option character, or <code>'\0'</code>
476 const char short_name;
9e2c879b 477
45ad74d3
SM
478 /// Long option name (without the <code>\--</code> prefix), or \c NULL
479 const char * const long_name;
9e2c879b 480
45ad74d3
SM
481 /// \c true if this option has an argument
482 const bool with_arg;
7554f0b6 483} argpar_opt_descr_t;
9e2c879b
PP
484
485/*!
486@brief
487 Sentinel for an option descriptor array
488
489The typical usage is, for example:
490
491@code
7554f0b6 492const argpar_opt_descr_t descrs[] = {
9e2c879b
PP
493 { 0, 'd', NULL, false },
494 { 1, '\0', "squeeze", true },
495 { 2, 'm', "meow", true },
496 ARGPAR_OPT_DESCR_SENTINEL,
497};
498@endcode
499*/
45ad74d3
SM
500#define ARGPAR_OPT_DESCR_SENTINEL \
501 { \
502 -1, '\0', NULL, false \
503 }
9e2c879b
PP
504
505/*!
506@struct argpar_iter
507
508@brief
509 Opaque argpar iterator type
510
511argpar_iter_create() returns a pointer to such a type.
512*/
7554f0b6 513typedef struct argpar_iter argpar_iter_t;
9e2c879b
PP
514
515/*!
516@brief
517 Creates and returns an argument parsing iterator to parse the
518 original arguments \p argv of which the count is \p argc using the
519 option descriptors \p descrs.
520
521This function initializes the returned structure, but doesn't actually
522start parsing the arguments.
523
524argpar considers \em all the elements of \p argv, including the first
525one, so that you would typically pass <code>(argc - 1)</code> as \p argc
526and <code>\&argv[1]</code> as \p argv from what <code>main()</code>
527receives, or ignore the parsing item of the first call to
528argpar_iter_next().
529
8b95d883
PP
530\p *argv and \p *descrs must \em not change for all of:
531
532- The lifetime of the returned iterator (until you call
533 argpar_iter_destroy()).
534
535- The lifetime of any parsing item (until you call
536 argpar_item_destroy()) which argpar_iter_next() creates from the
537 returned iterator.
538
539- The lifetime of any parsing error (until you call
540 argpar_error_destroy()) which argpar_iter_next() creates from the
541 returned iterator.
9e2c879b
PP
542
543@param[in] argc
544 Number of original arguments to parse in \p argv.
545@param[in] argv
546 Original arguments to parse, of which the count is \p argc.
547@param[in] descrs
548 @parblock
549 Option descriptor array, terminated with #ARGPAR_OPT_DESCR_SENTINEL.
550
551 May contain duplicate entries.
552 @endparblock
553
554@returns
555 New argument parsing iterator, or \c NULL on memory error.
556
557@pre
558 \p argc is greater than 0.
559@pre
560 \p argv is not \c NULL.
561@pre
562 The first \p argc elements of \p argv are not \c NULL.
563@pre
564 \p descrs is not \c NULL.
565
566@sa
567 argpar_iter_destroy() -- Destroys an argument parsing iterator.
568*/
7554f0b6 569argpar_iter_t *argpar_iter_create(unsigned int argc, const char * const *argv,
45ad74d3 570 const argpar_opt_descr_t *descrs) ARGPAR_NOEXCEPT;
fc07e526 571
9e2c879b
PP
572/*!
573@brief
574 Destroys the argument parsing iterator \p iter.
575
576@param[in] iter
577 Argument parsing iterator to destroy (may be \c NULL).
578
579@sa
580 argpar_iter_create() -- Creates an argument parsing iterator.
581*/
7554f0b6 582void argpar_iter_destroy(argpar_iter_t *iter) ARGPAR_NOEXCEPT;
fc07e526 583
9e2c879b
PP
584/*!
585@brief
586 Return type of argpar_iter_next().
10197dcc
PP
587
588Error status enumerators have a negative value.
9e2c879b 589*/
45ad74d3
SM
590typedef enum argpar_iter_next_status
591{
592 /// Success
593 ARGPAR_ITER_NEXT_STATUS_OK,
9e2c879b 594
45ad74d3
SM
595 /// End of iteration (no more original arguments to parse)
596 ARGPAR_ITER_NEXT_STATUS_END,
9e2c879b 597
45ad74d3
SM
598 /// Parsing error
599 ARGPAR_ITER_NEXT_STATUS_ERROR = -1,
9e2c879b 600
45ad74d3
SM
601 /// Memory error
602 ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY = -12,
7554f0b6 603} argpar_iter_next_status_t;
fc07e526 604
9e2c879b
PP
605/*!
606@brief
607 Sets \p *item to the next item of the argument parsing iterator
608 \p iter and advances \p iter.
609
610If 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
1c881812
PP
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.
9e2c879b 626
8b95d883 627 Destroy \p *error with argpar_error_destroy().
9e2c879b
PP
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*/
45ad74d3
SM
638argpar_iter_next_status_t argpar_iter_next(argpar_iter_t *iter, const argpar_item_t **item,
639 const argpar_error_t **error) ARGPAR_NOEXCEPT;
fc07e526
SM
640
641/*
642 * Returns the number of ingested elements from `argv`, as passed to
643 * argpar_iter_create() to create `*iter`, that were required to produce
644 * the previously returned items.
645 */
9e2c879b
PP
646
647/*!
648@brief
649 Returns the number of ingested original arguments (in
8b95d883 650 \p argv, as passed to argpar_iter_create() to create \p iter) that
9e2c879b
PP
651 the parser ingested to produce the \em previous parsing items.
652
653@param[in] iter
654 Argument parsing iterator of which to get the number of ingested
655 original arguments.
656
657@returns
658 Number of original arguments which \p iter ingested.
659
660@pre
661 \p iter is not \c NULL.
662*/
45ad74d3 663unsigned int argpar_iter_ingested_orig_args(const argpar_iter_t *iter) ARGPAR_NOEXCEPT;
fc07e526 664
9e2c879b
PP
665/// @}
666
667/// @}
fc07e526 668
6ad7927f
SM
669#if defined(__cplusplus)
670}
671#endif
672
fe5a18f8 673#endif /* ARGPAR_ARGPAR_H */
This page took 0.058318 seconds and 4 git commands to generate.