]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/lib/librte_cmdline/cmdline_parse_num.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / lib / librte_cmdline / cmdline_parse_num.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation.
7c673cae
FG
3 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4 * All rights reserved.
7c673cae
FG
5 */
6
7#include <stdio.h>
8#include <stdint.h>
9#include <inttypes.h>
10#include <ctype.h>
11#include <string.h>
12#include <stdarg.h>
13#include <errno.h>
14#include <rte_string_fns.h>
15
16#include "cmdline_parse.h"
17#include "cmdline_parse_num.h"
18
19#ifdef RTE_LIBRTE_CMDLINE_DEBUG
20#define debug_printf(args...) printf(args)
21#else
22#define debug_printf(args...) do {} while(0)
23#endif
24
25struct cmdline_token_ops cmdline_token_num_ops = {
26 .parse = cmdline_parse_num,
27 .complete_get_nb = NULL,
28 .complete_get_elt = NULL,
29 .get_help = cmdline_get_help_num,
30};
31
32
33enum num_parse_state_t {
34 START,
35 DEC_NEG,
36 BIN,
37 HEX,
38
39 ERROR,
40
41 FIRST_OK, /* not used */
42 ZERO_OK,
43 HEX_OK,
44 OCTAL_OK,
45 BIN_OK,
46 DEC_NEG_OK,
47 DEC_POS_OK,
48};
49
50/* Keep it sync with enum in .h */
51static const char * num_help[] = {
52 "UINT8", "UINT16", "UINT32", "UINT64",
53 "INT8", "INT16", "INT32", "INT64",
54};
55
56static inline int
57add_to_res(unsigned int c, uint64_t *res, unsigned int base)
58{
59 /* overflow */
60 if ( (UINT64_MAX - c) / base < *res ) {
61 return -1;
62 }
63
64 *res = (uint64_t) (*res * base + c);
65 return 0;
66}
67
68static int
69check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
70{
71 switch (nd->type) {
72 case INT8:
73 case UINT8:
74 if (ressize < sizeof(int8_t))
75 return -1;
76 break;
77 case INT16:
78 case UINT16:
79 if (ressize < sizeof(int16_t))
80 return -1;
81 break;
82 case INT32:
83 case UINT32:
84 if (ressize < sizeof(int32_t))
85 return -1;
86 break;
87 case INT64:
88 case UINT64:
89 if (ressize < sizeof(int64_t))
90 return -1;
91 break;
92 default:
93 return -1;
94 }
95 return 0;
96}
97
98/* parse an int */
99int
100cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
101 unsigned ressize)
102{
103 struct cmdline_token_num_data nd;
104 enum num_parse_state_t st = START;
105 const char * buf;
106 char c;
107 uint64_t res1 = 0;
108
109 if (!tk)
110 return -1;
111
112 if (!srcbuf || !*srcbuf)
113 return -1;
114
115 buf = srcbuf;
116 c = *buf;
117
118 memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
119
120 /* check that we have enough room in res */
121 if (res) {
122 if (check_res_size(&nd, ressize) < 0)
123 return -1;
124 }
125
126 while ( st != ERROR && c && ! cmdline_isendoftoken(c) ) {
127 debug_printf("%c %x -> ", c, c);
128 switch (st) {
129 case START:
130 if (c == '-') {
131 st = DEC_NEG;
132 }
133 else if (c == '0') {
134 st = ZERO_OK;
135 }
136 else if (c >= '1' && c <= '9') {
137 if (add_to_res(c - '0', &res1, 10) < 0)
138 st = ERROR;
139 else
140 st = DEC_POS_OK;
141 }
142 else {
143 st = ERROR;
144 }
145 break;
146
147 case ZERO_OK:
148 if (c == 'x') {
149 st = HEX;
150 }
151 else if (c == 'b') {
152 st = BIN;
153 }
154 else if (c >= '0' && c <= '7') {
155 if (add_to_res(c - '0', &res1, 10) < 0)
156 st = ERROR;
157 else
158 st = OCTAL_OK;
159 }
160 else {
161 st = ERROR;
162 }
163 break;
164
165 case DEC_NEG:
166 if (c >= '0' && c <= '9') {
167 if (add_to_res(c - '0', &res1, 10) < 0)
168 st = ERROR;
169 else
170 st = DEC_NEG_OK;
171 }
172 else {
173 st = ERROR;
174 }
175 break;
176
177 case DEC_NEG_OK:
178 if (c >= '0' && c <= '9') {
179 if (add_to_res(c - '0', &res1, 10) < 0)
180 st = ERROR;
181 }
182 else {
183 st = ERROR;
184 }
185 break;
186
187 case DEC_POS_OK:
188 if (c >= '0' && c <= '9') {
189 if (add_to_res(c - '0', &res1, 10) < 0)
190 st = ERROR;
191 }
192 else {
193 st = ERROR;
194 }
195 break;
196
197 case HEX:
198 st = HEX_OK;
f67539c2 199 /* fall-through */
7c673cae
FG
200 case HEX_OK:
201 if (c >= '0' && c <= '9') {
202 if (add_to_res(c - '0', &res1, 16) < 0)
203 st = ERROR;
204 }
205 else if (c >= 'a' && c <= 'f') {
206 if (add_to_res(c - 'a' + 10, &res1, 16) < 0)
207 st = ERROR;
208 }
209 else if (c >= 'A' && c <= 'F') {
210 if (add_to_res(c - 'A' + 10, &res1, 16) < 0)
211 st = ERROR;
212 }
213 else {
214 st = ERROR;
215 }
216 break;
217
218
219 case OCTAL_OK:
220 if (c >= '0' && c <= '7') {
221 if (add_to_res(c - '0', &res1, 8) < 0)
222 st = ERROR;
223 }
224 else {
225 st = ERROR;
226 }
227 break;
228
229 case BIN:
230 st = BIN_OK;
11fdf7f2 231 /* fall-through */
7c673cae
FG
232 case BIN_OK:
233 if (c >= '0' && c <= '1') {
234 if (add_to_res(c - '0', &res1, 2) < 0)
235 st = ERROR;
236 }
237 else {
238 st = ERROR;
239 }
240 break;
241 default:
242 debug_printf("not impl ");
243
244 }
245
246 debug_printf("(%"PRIu64")\n", res1);
247
248 buf ++;
249 c = *buf;
250
251 /* token too long */
252 if (buf-srcbuf > 127)
253 return -1;
254 }
255
256 switch (st) {
257 case ZERO_OK:
258 case DEC_POS_OK:
259 case HEX_OK:
260 case OCTAL_OK:
261 case BIN_OK:
262 if ( nd.type == INT8 && res1 <= INT8_MAX ) {
263 if (res) *(int8_t *)res = (int8_t) res1;
264 return buf-srcbuf;
265 }
266 else if ( nd.type == INT16 && res1 <= INT16_MAX ) {
267 if (res) *(int16_t *)res = (int16_t) res1;
268 return buf-srcbuf;
269 }
270 else if ( nd.type == INT32 && res1 <= INT32_MAX ) {
271 if (res) *(int32_t *)res = (int32_t) res1;
272 return buf-srcbuf;
273 }
274 else if ( nd.type == INT64 && res1 <= INT64_MAX ) {
275 if (res) *(int64_t *)res = (int64_t) res1;
276 return buf-srcbuf;
277 }
278 else if ( nd.type == UINT8 && res1 <= UINT8_MAX ) {
279 if (res) *(uint8_t *)res = (uint8_t) res1;
280 return buf-srcbuf;
281 }
282 else if (nd.type == UINT16 && res1 <= UINT16_MAX ) {
283 if (res) *(uint16_t *)res = (uint16_t) res1;
284 return buf-srcbuf;
285 }
286 else if ( nd.type == UINT32 && res1 <= UINT32_MAX ) {
287 if (res) *(uint32_t *)res = (uint32_t) res1;
288 return buf-srcbuf;
289 }
290 else if ( nd.type == UINT64 ) {
291 if (res) *(uint64_t *)res = res1;
292 return buf-srcbuf;
293 }
294 else {
295 return -1;
296 }
297 break;
298
299 case DEC_NEG_OK:
300 if ( nd.type == INT8 && res1 <= INT8_MAX + 1 ) {
301 if (res) *(int8_t *)res = (int8_t) (-res1);
302 return buf-srcbuf;
303 }
304 else if ( nd.type == INT16 && res1 <= (uint16_t)INT16_MAX + 1 ) {
305 if (res) *(int16_t *)res = (int16_t) (-res1);
306 return buf-srcbuf;
307 }
308 else if ( nd.type == INT32 && res1 <= (uint32_t)INT32_MAX + 1 ) {
309 if (res) *(int32_t *)res = (int32_t) (-res1);
310 return buf-srcbuf;
311 }
312 else if ( nd.type == INT64 && res1 <= (uint64_t)INT64_MAX + 1 ) {
313 if (res) *(int64_t *)res = (int64_t) (-res1);
314 return buf-srcbuf;
315 }
316 else {
317 return -1;
318 }
319 break;
320 default:
321 debug_printf("error\n");
322 return -1;
323 }
324}
325
326
327/* parse an int */
328int
329cmdline_get_help_num(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size)
330{
331 struct cmdline_token_num_data nd;
332 int ret;
333
334 if (!tk)
335 return -1;
336
337 memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
338
339 /* should not happen.... don't so this test */
340 /* if (nd.type >= (sizeof(num_help)/sizeof(const char *))) */
341 /* return -1; */
342
9f95a23c 343 ret = strlcpy(dstbuf, num_help[nd.type], size);
7c673cae
FG
344 if (ret < 0)
345 return -1;
346 dstbuf[size-1] = '\0';
347 return 0;
348}