Coverage Report

Created: 2024-07-23 06:24

/src/pjsip/pjlib/include/pj/argparse.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008-2024 Teluu Inc. (http://www.teluu.com)
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 */
18
#ifndef __PJ_ARGPARSE_H__
19
#define __PJ_ARGPARSE_H__
20
21
/**
22
 * @file argparse.h
23
 * @brief Command line argument parser
24
 */
25
#include <pj/ctype.h>
26
#include <pj/errno.h>
27
#include <pj/string.h>
28
29
PJ_BEGIN_DECL
30
31
/**
32
 * Define function to display parsing error.
33
 */
34
#ifndef PJ_ARGPARSE_ERROR
35
#  include <stdio.h>
36
#  define PJ_ARGPARSE_ERROR(fmt, arg) printf(fmt "\n", arg)
37
#endif
38
39
40
/**
41
 * @defgroup PJ_ARGPARSE Command line argument parser
42
 * @ingroup PJ_MISC
43
 * @{
44
 *
45
 * This module provides header only utilities to parse command line arguments.
46
 * This is mostly used by PJSIP test and sample apps. Note that there is
47
 * getopt() implementation in PJLIB-UTIL (but it's in PJLIB-UTIL, so it can't
48
 * be used by PJLIB).
49
 *
50
 * Limitations:
51
 * - the utility only supports white space(s) as separator between an option
52
 *   and its value. Equal sign is not supported.
53
 * - the utility does not support double dash (--) as separator between options
54
 *   and operands. It will keep treating arguments after -- as possible
55
 *   options.
56
 */
57
58
/**
59
 * Peek the next possible option from argv. An argument is considered an
60
 * option if it starts with "-".
61
 *
62
 * @param argv      The argv, which must be null terminated.
63
 *
64
 * @return          next option or NULL.
65
 */
66
PJ_INLINE(char*) pj_argparse_peek_next_option(char *const argv[])
67
0
{
68
0
    while (*argv) {
69
0
        const char *arg = *argv;
70
0
        if (*arg=='-') {
71
0
            return *argv;
72
0
        }
73
0
        ++argv;
74
0
    }
75
0
    return NULL;
76
0
}
77
78
/**
79
 * Check that an option exists, without modifying argv.
80
 *
81
 * @param argv      The argv, which must be null terminated.
82
 * @param opt       The option to find, e.g. "-h", "--help"
83
 *
84
 * @return          PJ_TRUE if the option exists, else PJ_FALSE.
85
 */
86
PJ_INLINE(pj_bool_t) pj_argparse_exists(char *const argv[], const char *opt)
87
0
{
88
0
    int i;
89
0
    for (i=1; argv[i]; ++i) {
90
0
        if (pj_ansi_strcmp(argv[i], opt)==0)
91
0
            return PJ_TRUE;
92
0
    }
93
0
    return PJ_FALSE;
94
0
}
95
96
/**
97
 * Check for an option and if it exists remove that option from argc/argv and
98
 * returns PJ_TRUE.
99
 *
100
 * @param argc      Pointer to argc.
101
 * @param argv      Null terminated argv.
102
 * @param opt       The option to find, e.g. "-h", "--help"
103
 *
104
 * @return          PJ_TRUE if the option exists, else PJ_FALSE.
105
 */
106
PJ_INLINE(pj_bool_t) pj_argparse_get_bool(int *argc, char *argv[],
107
                                          const char *opt)
108
0
{
109
0
    int i;
110
0
    for (i=1; argv[i]; ++i) {
111
0
        if (pj_ansi_strcmp(argv[i], opt)==0) {
112
0
            pj_memmove(&argv[i], &argv[i+1], ((*argc)-i)*sizeof(char*));
113
0
            (*argc)--;
114
0
            return PJ_TRUE;
115
0
        }
116
0
    }
117
0
    return PJ_FALSE;
118
0
}
119
120
/**
121
 * Check for an option and if it exists get the value and remove both
122
 * the option and the value from argc/argv. Note that the function only
123
 * supports whitespace(s) as separator between option and value (i.e. equal
124
 * sign is not supported, e.g. "--server=127.0.0.1" will not be parsed
125
 * correctly).
126
 *
127
 * @param argc          Pointer to argc.
128
 * @param argv          Null terminated argv.
129
 * @param opt           The option to find, e.g. "-t", "--type"
130
 * @param ptr_value     Pointer to receive the value.
131
 *
132
 * @return              - PJ_SUCCESS if the option exists and value is found
133
 *                        or if the option does not exist
134
 *                      - PJ_EINVAL if the option exits but value is not found
135
 */
136
PJ_INLINE(pj_status_t) pj_argparse_get_str(int *argc, char *argv[],
137
                                           const char *opt, char **ptr_value)
138
0
{
139
0
    int i;
140
0
    for (i=1; argv[i]; ++i) {
141
0
        if (pj_ansi_strcmp(argv[i], opt)==0) {
142
0
            pj_memmove(&argv[i], &argv[i+1], ((*argc)-i)*sizeof(char*));
143
0
            (*argc)--;
144
0
145
0
            if (argv[i]) {
146
0
                char *val = argv[i];
147
0
                pj_memmove(&argv[i], &argv[i+1], ((*argc)-i)*sizeof(char*));
148
0
                (*argc)--;
149
0
                *ptr_value = val;
150
0
                return PJ_SUCCESS;
151
0
            } else {
152
0
                PJ_ARGPARSE_ERROR("Error: missing value for %s argument",
153
0
                                  opt);
154
0
                return PJ_EINVAL;
155
0
            }
156
0
        }
157
0
    }
158
0
    return PJ_SUCCESS;
159
0
}
160
161
/**
162
 * Check for an option and if it exists, get the integer value and remove both
163
 * the option and the value from argc/argv. Note that the function only
164
 * supports whitespace(s) as separator between option and value (i.e. equal
165
 * sign is not supported, e.g. "--port=80" will not be parsed correctly).
166
 *
167
 * @param opt           The option to find, e.g. "-h", "--help"
168
 * @param argc          Pointer to argc.
169
 * @param argv          Null terminated argv.
170
 * @param ptr_value     Pointer to receive the value.
171
 *
172
 * @return              - PJ_SUCCESS if the option exists and value is found
173
 *                        or if the option does not exist
174
 *                      - PJ_EINVAL if the option exits but value is not found,
175
 *                        or if the value is not an integer.
176
 */
177
PJ_INLINE(pj_status_t) pj_argparse_get_int(int *argc, char *argv[],
178
                                           const char *opt, int *ptr_value)
179
0
{
180
0
    char *endptr, *sval=NULL;
181
0
    long val;
182
0
    pj_status_t status = pj_argparse_get_str(argc, argv, opt, &sval);
183
0
    if (status!=PJ_SUCCESS || !sval)
184
0
        return status;
185
0
186
0
    val = strtol(sval, &endptr, 10);
187
0
    if (*endptr) {
188
0
        PJ_ARGPARSE_ERROR("Error: invalid value for %s argument",
189
0
                          opt);
190
0
        return PJ_EINVAL;
191
0
    }
192
0
193
0
    *ptr_value = (int)val;
194
0
    return PJ_SUCCESS;
195
0
}
196
197
/**
198
 * @}
199
 */
200
201
PJ_END_DECL
202
203
204
#endif  /* __PJ_ARGPARSE_H__ */
205