VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strtonum.cpp@ 96563

Last change on this file since 96563 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 42.9 KB
Line 
1/* $Id: strtonum.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT - String To Number Conversion.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/string.h>
42#include "internal/iprt.h"
43
44#include <iprt/assert.h>
45#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
46#include <iprt/err.h>
47
48
49/*********************************************************************************************************************************
50* Global Variables *
51*********************************************************************************************************************************/
52extern const unsigned char g_auchDigits[256]; /* shared with strtofloat.cpp - add header? */
53
54/** 8-bit char -> digit.
55 * Non-digits have values 255 (most), 254 (zero), 253 (colon), 252 (space), 251 (dot).
56 *
57 * @note Also used by strtofloat.cpp
58 */
59const unsigned char g_auchDigits[256] =
60{
61 254,255,255,255,255,255,255,255,255,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
62 252,255,255,255,255,255,255,255,255,255,255,255,255,255,251,255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,253,255,255,255,255,255,
63 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
64 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
65 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
66 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
67 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
68 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
69};
70
71#define DIGITS_ZERO_TERM 254
72#define DIGITS_COLON 253
73#define DIGITS_SPACE 252
74#define DIGITS_DOT 251
75
76/** Approximated overflow shift checks. */
77static const char g_auchShift[36] =
78{
79 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 */
80 64, 64, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59
81};
82
83/*
84#include <stdio.h>
85int main()
86{
87 int i;
88 printf("static const unsigned char g_auchDigits[256] =\n"
89 "{");
90 for (i = 0; i < 256; i++)
91 {
92 int ch = 255;
93 if (i >= '0' && i <= '9')
94 ch = i - '0';
95 else if (i >= 'a' && i <= 'z')
96 ch = i - 'a' + 10;
97 else if (i >= 'A' && i <= 'Z')
98 ch = i - 'A' + 10;
99 else if (i == 0)
100 ch = 254;
101 else if (i == ':')
102 ch = 253;
103 else if (i == ' ' || i == '\t')
104 ch = 252;
105 else if (i == '.')
106 ch = 251;
107 if (i == 0)
108 printf("\n %3d", ch);
109 else if ((i % 32) == 0)
110 printf(",\n %3d", ch);
111 else
112 printf(",%3d", ch);
113 }
114 printf("\n"
115 "};\n");
116 return 0;
117}
118*/
119
120
121/**
122 * Converts a string representation of a number to a 64-bit unsigned number.
123 *
124 * @returns iprt status code.
125 * Warnings are used to indicate conversion problems.
126 * @retval VWRN_NUMBER_TOO_BIG
127 * @retval VWRN_NEGATIVE_UNSIGNED
128 * @retval VWRN_TRAILING_CHARS
129 * @retval VWRN_TRAILING_SPACES
130 * @retval VINF_SUCCESS
131 * @retval VERR_NO_DIGITS
132 *
133 * @param pszValue Pointer to the string value.
134 * @param ppszNext Where to store the pointer to the first char
135 * following the number. (Optional)
136 * @param uBaseAndMaxLen The low byte is the base of the representation, the
137 * upper 24 bits are the max length to parse. If the base
138 * is zero the function will look for known prefixes before
139 * defaulting to 10. A max length of zero means no length
140 * restriction.
141 * @param pu64 Where to store the converted number. (optional)
142 */
143RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint64_t *pu64)
144{
145 const char *psz = pszValue;
146 int iShift;
147 int rc;
148 uint64_t u64;
149 unsigned char uch;
150 bool fPositive;
151
152 /*
153 * Split the base and length limit (latter is chiefly for sscanf).
154 */
155 unsigned uBase = uBaseAndMaxLen & 0xff;
156 unsigned cchMax = uBaseAndMaxLen >> 8;
157 if (cchMax == 0)
158 cchMax = ~0U;
159 AssertStmt(uBase < RT_ELEMENTS(g_auchShift), uBase = 0);
160
161 /*
162 * Positive/Negative stuff.
163 */
164 fPositive = true;
165 while (cchMax > 0)
166 {
167 if (*psz == '+')
168 fPositive = true;
169 else if (*psz == '-')
170 fPositive = !fPositive;
171 else
172 break;
173 psz++;
174 cchMax--;
175 }
176
177 /*
178 * Check for hex prefix.
179 */
180 if (!uBase)
181 {
182 uBase = 10;
183 if (psz[0] == '0')
184 {
185 if ( psz[0] == '0'
186 && cchMax > 1
187 && (psz[1] == 'x' || psz[1] == 'X')
188 && g_auchDigits[(unsigned char)psz[2]] < 16)
189 {
190 uBase = 16;
191 psz += 2;
192 cchMax -= 2;
193 }
194 else if ( psz[0] == '0'
195 && g_auchDigits[(unsigned char)psz[1]] < 8)
196 uBase = 8; /* don't skip the zero, in case it's alone. */
197 }
198 }
199 else if ( uBase == 16
200 && psz[0] == '0'
201 && cchMax > 1
202 && (psz[1] == 'x' || psz[1] == 'X')
203 && g_auchDigits[(unsigned char)psz[2]] < 16)
204 {
205 cchMax -= 2;
206 psz += 2;
207 }
208
209 /*
210 * Interpret the value.
211 * Note: We only support ascii digits at this time... :-)
212 */
213 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
214 iShift = g_auchShift[uBase];
215 rc = VINF_SUCCESS;
216 u64 = 0;
217 while (cchMax > 0 && (uch = (unsigned char)*psz) != 0)
218 {
219 unsigned char chDigit = g_auchDigits[uch];
220 uint64_t u64Prev;
221
222 if (chDigit >= uBase)
223 break;
224
225 u64Prev = u64;
226 u64 *= uBase;
227 u64 += chDigit;
228 if (u64Prev > u64 || (u64Prev >> iShift))
229 rc = VWRN_NUMBER_TOO_BIG;
230 psz++;
231 cchMax--;
232 }
233
234 if (!fPositive)
235 {
236 if (rc == VINF_SUCCESS)
237 rc = VWRN_NEGATIVE_UNSIGNED;
238 u64 = -(int64_t)u64;
239 }
240
241 if (pu64)
242 *pu64 = u64;
243
244 if (psz == pszValue)
245 rc = VERR_NO_DIGITS;
246
247 if (ppszNext)
248 *ppszNext = (char *)psz;
249
250 /*
251 * Warn about trailing chars/spaces.
252 */
253 if ( rc == VINF_SUCCESS
254 && *psz
255 && cchMax > 0)
256 {
257 while (cchMax > 0 && (*psz == ' ' || *psz == '\t'))
258 psz++, cchMax--;
259 rc = cchMax > 0 && *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
260 }
261
262 return rc;
263}
264RT_EXPORT_SYMBOL(RTStrToUInt64Ex);
265
266
267/**
268 * Converts a string representation of a number to a 64-bit unsigned number,
269 * making sure the full string is converted.
270 *
271 * @returns iprt status code.
272 * Warnings are used to indicate conversion problems.
273 * @retval VWRN_NUMBER_TOO_BIG
274 * @retval VWRN_NEGATIVE_UNSIGNED
275 * @retval VINF_SUCCESS
276 * @retval VERR_NO_DIGITS
277 * @retval VERR_TRAILING_SPACES
278 * @retval VERR_TRAILING_CHARS
279 *
280 * @param pszValue Pointer to the string value.
281 * @param uBaseAndMaxLen The low byte is the base of the representation, the
282 * upper 24 bits are the max length to parse. If the base
283 * is zero the function will look for known prefixes before
284 * defaulting to 10. A max length of zero means no length
285 * restriction.
286 * @param pu64 Where to store the converted number. (optional)
287 */
288RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, uint64_t *pu64)
289{
290 char *psz;
291 int rc = RTStrToUInt64Ex(pszValue, &psz, uBaseAndMaxLen, pu64);
292 if (RT_SUCCESS(rc) && *psz)
293 {
294 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
295 rc = -rc;
296 else if (rc != VINF_SUCCESS)
297 {
298 unsigned cchMax = uBaseAndMaxLen >> 8;
299 if (!cchMax)
300 cchMax = ~0U;
301 else
302 cchMax -= (unsigned)(psz - pszValue);
303 if (cchMax > 0)
304 {
305 while (cchMax > 0 && (*psz == ' ' || *psz == '\t'))
306 psz++, cchMax--;
307 rc = cchMax > 0 && *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
308 }
309 }
310 }
311 return rc;
312}
313RT_EXPORT_SYMBOL(RTStrToUInt64Full);
314
315
316/**
317 * Converts a string representation of a number to a 64-bit unsigned number.
318 * The base is guessed.
319 *
320 * @returns 64-bit unsigned number on success.
321 * @returns 0 on failure.
322 * @param pszValue Pointer to the string value.
323 */
324RTDECL(uint64_t) RTStrToUInt64(const char *pszValue)
325{
326 uint64_t u64;
327 int rc = RTStrToUInt64Ex(pszValue, NULL, 0, &u64);
328 if (RT_SUCCESS(rc))
329 return u64;
330 return 0;
331}
332RT_EXPORT_SYMBOL(RTStrToUInt64);
333
334
335/**
336 * Converts a string representation of a number to a 32-bit unsigned number.
337 *
338 * @returns iprt status code.
339 * Warnings are used to indicate conversion problems.
340 * @retval VWRN_NUMBER_TOO_BIG
341 * @retval VWRN_NEGATIVE_UNSIGNED
342 * @retval VWRN_TRAILING_CHARS
343 * @retval VWRN_TRAILING_SPACES
344 * @retval VINF_SUCCESS
345 * @retval VERR_NO_DIGITS
346 *
347 * @param pszValue Pointer to the string value.
348 * @param ppszNext Where to store the pointer to the first char
349 * following the number. (Optional)
350 * @param uBaseAndMaxLen The low byte is the base of the representation, the
351 * upper 24 bits are the max length to parse. If the base
352 * is zero the function will look for known prefixes before
353 * defaulting to 10. A max length of zero means no length
354 * restriction.
355 * @param pu32 Where to store the converted number. (optional)
356 */
357RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint32_t *pu32)
358{
359 uint64_t u64;
360 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64);
361 if (RT_SUCCESS(rc))
362 {
363 if (u64 & ~0xffffffffULL)
364 rc = VWRN_NUMBER_TOO_BIG;
365 }
366 if (pu32)
367 *pu32 = (uint32_t)u64;
368 return rc;
369}
370RT_EXPORT_SYMBOL(RTStrToUInt32Ex);
371
372
373/**
374 * Converts a string representation of a number to a 32-bit unsigned number,
375 * making sure the full string is converted.
376 *
377 * @returns iprt status code.
378 * Warnings are used to indicate conversion problems.
379 * @retval VWRN_NUMBER_TOO_BIG
380 * @retval VWRN_NEGATIVE_UNSIGNED
381 * @retval VINF_SUCCESS
382 * @retval VERR_NO_DIGITS
383 * @retval VERR_TRAILING_SPACES
384 * @retval VERR_TRAILING_CHARS
385 *
386 * @param pszValue Pointer to the string value.
387 * @param uBaseAndMaxLen The low byte is the base of the representation, the
388 * upper 24 bits are the max length to parse. If the base
389 * is zero the function will look for known prefixes before
390 * defaulting to 10. A max length of zero means no length
391 * restriction.
392 * @param pu32 Where to store the converted number. (optional)
393 */
394RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, uint32_t *pu32)
395{
396 uint64_t u64;
397 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64);
398 if (RT_SUCCESS(rc))
399 {
400 if (u64 & ~0xffffffffULL)
401 rc = VWRN_NUMBER_TOO_BIG;
402 }
403 if (pu32)
404 *pu32 = (uint32_t)u64;
405 return rc;
406}
407RT_EXPORT_SYMBOL(RTStrToUInt32Full);
408
409
410/**
411 * Converts a string representation of a number to a 64-bit unsigned number.
412 * The base is guessed.
413 *
414 * @returns 32-bit unsigned number on success.
415 * @returns 0 on failure.
416 * @param pszValue Pointer to the string value.
417 */
418RTDECL(uint32_t) RTStrToUInt32(const char *pszValue)
419{
420 uint32_t u32;
421 int rc = RTStrToUInt32Ex(pszValue, NULL, 0, &u32);
422 if (RT_SUCCESS(rc))
423 return u32;
424 return 0;
425}
426RT_EXPORT_SYMBOL(RTStrToUInt32);
427
428
429/**
430 * Converts a string representation of a number to a 16-bit unsigned number.
431 *
432 * @returns iprt status code.
433 * Warnings are used to indicate conversion problems.
434 * @retval VWRN_NUMBER_TOO_BIG
435 * @retval VWRN_NEGATIVE_UNSIGNED
436 * @retval VWRN_TRAILING_CHARS
437 * @retval VWRN_TRAILING_SPACES
438 * @retval VINF_SUCCESS
439 * @retval VERR_NO_DIGITS
440 *
441 * @param pszValue Pointer to the string value.
442 * @param ppszNext Where to store the pointer to the first char
443 * following the number. (Optional)
444 * @param uBaseAndMaxLen The low byte is the base of the representation, the
445 * upper 24 bits are the max length to parse. If the base
446 * is zero the function will look for known prefixes before
447 * defaulting to 10. A max length of zero means no length
448 * restriction.
449 * @param pu16 Where to store the converted number. (optional)
450 */
451RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint16_t *pu16)
452{
453 uint64_t u64;
454 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64);
455 if (RT_SUCCESS(rc))
456 {
457 if (u64 & ~0xffffULL)
458 rc = VWRN_NUMBER_TOO_BIG;
459 }
460 if (pu16)
461 *pu16 = (uint16_t)u64;
462 return rc;
463}
464RT_EXPORT_SYMBOL(RTStrToUInt16Ex);
465
466
467/**
468 * Converts a string representation of a number to a 16-bit unsigned number,
469 * making sure the full string is converted.
470 *
471 * @returns iprt status code.
472 * Warnings are used to indicate conversion problems.
473 * @retval VWRN_NUMBER_TOO_BIG
474 * @retval VWRN_NEGATIVE_UNSIGNED
475 * @retval VINF_SUCCESS
476 * @retval VERR_NO_DIGITS
477 * @retval VERR_TRAILING_SPACES
478 * @retval VERR_TRAILING_CHARS
479 *
480 * @param pszValue Pointer to the string value.
481 * @param uBaseAndMaxLen The low byte is the base of the representation, the
482 * upper 24 bits are the max length to parse. If the base
483 * is zero the function will look for known prefixes before
484 * defaulting to 10. A max length of zero means no length
485 * restriction.
486 * @param pu16 Where to store the converted number. (optional)
487 */
488RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, uint16_t *pu16)
489{
490 uint64_t u64;
491 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64);
492 if (RT_SUCCESS(rc))
493 {
494 if (u64 & ~0xffffULL)
495 rc = VWRN_NUMBER_TOO_BIG;
496 }
497 if (pu16)
498 *pu16 = (uint16_t)u64;
499 return rc;
500}
501RT_EXPORT_SYMBOL(RTStrToUInt16Full);
502
503
504/**
505 * Converts a string representation of a number to a 16-bit unsigned number.
506 * The base is guessed.
507 *
508 * @returns 16-bit unsigned number on success.
509 * @returns 0 on failure.
510 * @param pszValue Pointer to the string value.
511 */
512RTDECL(uint16_t) RTStrToUInt16(const char *pszValue)
513{
514 uint16_t u16;
515 int rc = RTStrToUInt16Ex(pszValue, NULL, 0, &u16);
516 if (RT_SUCCESS(rc))
517 return u16;
518 return 0;
519}
520RT_EXPORT_SYMBOL(RTStrToUInt16);
521
522
523/**
524 * Converts a string representation of a number to a 8-bit unsigned number.
525 *
526 * @returns iprt status code.
527 * Warnings are used to indicate conversion problems.
528 * @retval VWRN_NUMBER_TOO_BIG
529 * @retval VWRN_NEGATIVE_UNSIGNED
530 * @retval VWRN_TRAILING_CHARS
531 * @retval VWRN_TRAILING_SPACES
532 * @retval VINF_SUCCESS
533 * @retval VERR_NO_DIGITS
534 *
535 * @param pszValue Pointer to the string value.
536 * @param ppszNext Where to store the pointer to the first char
537 * following the number. (Optional)
538 * @param uBaseAndMaxLen The low byte is the base of the representation, the
539 * upper 24 bits are the max length to parse. If the base
540 * is zero the function will look for known prefixes before
541 * defaulting to 10. A max length of zero means no length
542 * restriction.
543 * @param pu8 Where to store the converted number. (optional)
544 */
545RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint8_t *pu8)
546{
547 uint64_t u64;
548 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64);
549 if (RT_SUCCESS(rc))
550 {
551 if (u64 & ~0xffULL)
552 rc = VWRN_NUMBER_TOO_BIG;
553 }
554 if (pu8)
555 *pu8 = (uint8_t)u64;
556 return rc;
557}
558RT_EXPORT_SYMBOL(RTStrToUInt8Ex);
559
560
561/**
562 * Converts a string representation of a number to a 8-bit unsigned number,
563 * making sure the full string is converted.
564 *
565 * @returns iprt status code.
566 * Warnings are used to indicate conversion problems.
567 * @retval VWRN_NUMBER_TOO_BIG
568 * @retval VWRN_NEGATIVE_UNSIGNED
569 * @retval VINF_SUCCESS
570 * @retval VERR_NO_DIGITS
571 * @retval VERR_TRAILING_SPACES
572 * @retval VERR_TRAILING_CHARS
573 *
574 * @param pszValue Pointer to the string value.
575 * @param uBaseAndMaxLen The low byte is the base of the representation, the
576 * upper 24 bits are the max length to parse. If the base
577 * is zero the function will look for known prefixes before
578 * defaulting to 10. A max length of zero means no length
579 * restriction.
580 * @param pu8 Where to store the converted number. (optional)
581 */
582RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, uint8_t *pu8)
583{
584 uint64_t u64;
585 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64);
586 if (RT_SUCCESS(rc))
587 {
588 if (u64 & ~0xffULL)
589 rc = VWRN_NUMBER_TOO_BIG;
590 }
591 if (pu8)
592 *pu8 = (uint8_t)u64;
593 return rc;
594}
595RT_EXPORT_SYMBOL(RTStrToUInt8Full);
596
597
598/**
599 * Converts a string representation of a number to a 8-bit unsigned number.
600 * The base is guessed.
601 *
602 * @returns 8-bit unsigned number on success.
603 * @returns 0 on failure.
604 * @param pszValue Pointer to the string value.
605 */
606RTDECL(uint8_t) RTStrToUInt8(const char *pszValue)
607{
608 uint8_t u8;
609 int rc = RTStrToUInt8Ex(pszValue, NULL, 0, &u8);
610 if (RT_SUCCESS(rc))
611 return u8;
612 return 0;
613}
614RT_EXPORT_SYMBOL(RTStrToUInt8);
615
616
617
618
619
620
621
622/**
623 * Converts a string representation of a number to a 64-bit signed number.
624 *
625 * @returns iprt status code.
626 * Warnings are used to indicate conversion problems.
627 * @retval VWRN_NUMBER_TOO_BIG
628 * @retval VWRN_TRAILING_CHARS
629 * @retval VWRN_TRAILING_SPACES
630 * @retval VINF_SUCCESS
631 * @retval VERR_NO_DIGITS
632 *
633 * @param pszValue Pointer to the string value.
634 * @param ppszNext Where to store the pointer to the first char
635 * following the number. (Optional)
636 * @param uBaseAndMaxLen The low byte is the base of the representation, the
637 * upper 24 bits are the max length to parse. If the base
638 * is zero the function will look for known prefixes before
639 * defaulting to 10. A max length of zero means no length
640 * restriction.
641 * @param pi64 Where to store the converted number. (optional)
642 */
643RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int64_t *pi64)
644{
645 const char *psz = pszValue;
646 int iShift;
647 int rc;
648 uint64_t u64;
649 unsigned char uch;
650 bool fPositive;
651
652 /*
653 * Split the base and length limit (latter is chiefly for sscanf).
654 */
655 unsigned uBase = uBaseAndMaxLen & 0xff;
656 unsigned cchMax = uBaseAndMaxLen >> 8;
657 if (cchMax == 0)
658 cchMax = ~0U;
659 AssertStmt(uBase < RT_ELEMENTS(g_auchShift), uBase = 0);
660
661 /*
662 * Positive/Negative stuff.
663 */
664 fPositive = true;
665 while (cchMax > 0)
666 {
667 if (*psz == '+')
668 fPositive = true;
669 else if (*psz == '-')
670 fPositive = !fPositive;
671 else
672 break;
673 psz++;
674 cchMax--;
675 }
676
677 /*
678 * Check for hex prefix.
679 */
680 if (!uBase)
681 {
682 uBase = 10;
683 if (psz[0] == '0')
684 {
685 if ( psz[0] == '0'
686 && cchMax > 1
687 && (psz[1] == 'x' || psz[1] == 'X')
688 && g_auchDigits[(unsigned char)psz[2]] < 16)
689 {
690 uBase = 16;
691 psz += 2;
692 cchMax -= 2;
693 }
694 else if ( psz[0] == '0'
695 && g_auchDigits[(unsigned char)psz[1]] < 8)
696 uBase = 8; /* don't skip the zero, in case it's alone. */
697 }
698 }
699 else if ( uBase == 16
700 && psz[0] == '0'
701 && cchMax > 1
702 && (psz[1] == 'x' || psz[1] == 'X')
703 && g_auchDigits[(unsigned char)psz[2]] < 16)
704 {
705 cchMax -= 2;
706 psz += 2;
707 }
708
709 /*
710 * Interpret the value.
711 * Note: We only support ascii digits at this time... :-)
712 */
713 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
714 iShift = g_auchShift[uBase];
715 rc = VINF_SUCCESS;
716 u64 = 0;
717 while (cchMax > 0 && (uch = (unsigned char)*psz) != 0)
718 {
719 unsigned char chDigit = g_auchDigits[uch];
720 uint64_t u64Prev;
721
722 if (chDigit >= uBase)
723 break;
724
725 u64Prev = u64;
726 u64 *= uBase;
727 u64 += chDigit;
728 if (u64Prev > u64 || (u64Prev >> iShift))
729 rc = VWRN_NUMBER_TOO_BIG;
730 psz++;
731 cchMax--;
732 }
733
734 /* Mixing pi64 assigning and overflow checks is to pacify a tstRTCRest-1
735 asan overflow warning. */
736 if (!(u64 & RT_BIT_64(63)))
737 {
738 if (psz == pszValue)
739 rc = VERR_NO_DIGITS;
740 if (pi64)
741 *pi64 = fPositive ? u64 : -(int64_t)u64;
742 }
743 else if (!fPositive && u64 == RT_BIT_64(63))
744 {
745 if (pi64)
746 *pi64 = INT64_MIN;
747 }
748 else
749 {
750 rc = VWRN_NUMBER_TOO_BIG;
751 if (pi64)
752 *pi64 = fPositive ? u64 : -(int64_t)u64;
753 }
754
755 if (ppszNext)
756 *ppszNext = (char *)psz;
757
758 /*
759 * Warn about trailing chars/spaces.
760 */
761 if ( rc == VINF_SUCCESS
762 && cchMax > 0
763 && *psz)
764 {
765 while (cchMax > 0 && (*psz == ' ' || *psz == '\t'))
766 psz++, cchMax--;
767 rc = cchMax > 0 && *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
768 }
769
770 return rc;
771}
772RT_EXPORT_SYMBOL(RTStrToInt64Ex);
773
774
775/**
776 * Converts a string representation of a number to a 64-bit signed number,
777 * making sure the full string is converted.
778 *
779 * @returns iprt status code.
780 * Warnings are used to indicate conversion problems.
781 * @retval VWRN_NUMBER_TOO_BIG
782 * @retval VINF_SUCCESS
783 * @retval VERR_TRAILING_CHARS
784 * @retval VERR_TRAILING_SPACES
785 * @retval VERR_NO_DIGITS
786 *
787 * @param pszValue Pointer to the string value.
788 * @param uBaseAndMaxLen The low byte is the base of the representation, the
789 * upper 24 bits are the max length to parse. If the base
790 * is zero the function will look for known prefixes before
791 * defaulting to 10. A max length of zero means no length
792 * restriction.
793 * @param pi64 Where to store the converted number. (optional)
794 */
795RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, int64_t *pi64)
796{
797 char *psz;
798 int rc = RTStrToInt64Ex(pszValue, &psz, uBaseAndMaxLen, pi64);
799 if (RT_SUCCESS(rc) && *psz)
800 {
801 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
802 rc = -rc;
803 else if (rc != VINF_SUCCESS)
804 {
805 unsigned cchMax = uBaseAndMaxLen >> 8;
806 if (!cchMax)
807 cchMax = ~0U;
808 else
809 cchMax -= (unsigned)(psz - pszValue);
810 if (cchMax > 0)
811 {
812 while (cchMax > 0 && (*psz == ' ' || *psz == '\t'))
813 psz++, cchMax--;
814 rc = cchMax > 0 && *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
815 }
816 }
817 }
818 return rc;
819}
820RT_EXPORT_SYMBOL(RTStrToInt64Full);
821
822
823/**
824 * Converts a string representation of a number to a 64-bit signed number.
825 * The base is guessed.
826 *
827 * @returns 64-bit signed number on success.
828 * @returns 0 on failure.
829 * @param pszValue Pointer to the string value.
830 */
831RTDECL(int64_t) RTStrToInt64(const char *pszValue)
832{
833 int64_t i64;
834 int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
835 if (RT_SUCCESS(rc))
836 return i64;
837 return 0;
838}
839RT_EXPORT_SYMBOL(RTStrToInt64);
840
841
842/**
843 * Converts a string representation of a number to a 32-bit signed number.
844 *
845 * @returns iprt status code.
846 * Warnings are used to indicate conversion problems.
847 * @retval VWRN_NUMBER_TOO_BIG
848 * @retval VWRN_TRAILING_CHARS
849 * @retval VWRN_TRAILING_SPACES
850 * @retval VINF_SUCCESS
851 * @retval VERR_NO_DIGITS
852 *
853 * @param pszValue Pointer to the string value.
854 * @param ppszNext Where to store the pointer to the first char
855 * following the number. (Optional)
856 * @param uBaseAndMaxLen The low byte is the base of the representation, the
857 * upper 24 bits are the max length to parse. If the base
858 * is zero the function will look for known prefixes before
859 * defaulting to 10. A max length of zero means no length
860 * restriction.
861 * @param pi32 Where to store the converted number. (optional)
862 */
863RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int32_t *pi32)
864{
865 int64_t i64;
866 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64);
867 if (RT_SUCCESS(rc))
868 {
869 int32_t i32 = (int32_t)i64;
870 if (i64 != (int64_t)i32)
871 rc = VWRN_NUMBER_TOO_BIG;
872 }
873 if (pi32)
874 *pi32 = (int32_t)i64;
875 return rc;
876}
877RT_EXPORT_SYMBOL(RTStrToInt32Ex);
878
879
880/**
881 * Converts a string representation of a number to a 32-bit signed number,
882 * making sure the full string is converted.
883 *
884 * @returns iprt status code.
885 * Warnings are used to indicate conversion problems.
886 * @retval VWRN_NUMBER_TOO_BIG
887 * @retval VINF_SUCCESS
888 * @retval VERR_TRAILING_CHARS
889 * @retval VERR_TRAILING_SPACES
890 * @retval VERR_NO_DIGITS
891 *
892 * @param pszValue Pointer to the string value.
893 * @param uBaseAndMaxLen The low byte is the base of the representation, the
894 * upper 24 bits are the max length to parse. If the base
895 * is zero the function will look for known prefixes before
896 * defaulting to 10. A max length of zero means no length
897 * restriction.
898 * @param pi32 Where to store the converted number. (optional)
899 */
900RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, int32_t *pi32)
901{
902 int64_t i64;
903 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64);
904 if (RT_SUCCESS(rc))
905 {
906 int32_t i32 = (int32_t)i64;
907 if (i64 != (int64_t)i32)
908 rc = VWRN_NUMBER_TOO_BIG;
909 }
910 if (pi32)
911 *pi32 = (int32_t)i64;
912 return rc;
913}
914RT_EXPORT_SYMBOL(RTStrToInt32Full);
915
916
917/**
918 * Converts a string representation of a number to a 32-bit signed number.
919 * The base is guessed.
920 *
921 * @returns 32-bit signed number on success.
922 * @returns 0 on failure.
923 * @param pszValue Pointer to the string value.
924 */
925RTDECL(int32_t) RTStrToInt32(const char *pszValue)
926{
927 int32_t i32;
928 int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
929 if (RT_SUCCESS(rc))
930 return i32;
931 return 0;
932}
933RT_EXPORT_SYMBOL(RTStrToInt32);
934
935
936/**
937 * Converts a string representation of a number to a 16-bit signed number.
938 *
939 * @returns iprt status code.
940 * Warnings are used to indicate conversion problems.
941 * @retval VWRN_NUMBER_TOO_BIG
942 * @retval VWRN_TRAILING_CHARS
943 * @retval VWRN_TRAILING_SPACES
944 * @retval VINF_SUCCESS
945 * @retval VERR_NO_DIGITS
946 *
947 * @param pszValue Pointer to the string value.
948 * @param ppszNext Where to store the pointer to the first char
949 * following the number. (Optional)
950 * @param pszValue Pointer to the string value.
951 * @param uBaseAndMaxLen The low byte is the base of the representation, the
952 * upper 24 bits are the max length to parse. If the base
953 * is zero the function will look for known prefixes before
954 * defaulting to 10. A max length of zero means no length
955 * restriction.
956 * @param pi16 Where to store the converted number. (optional)
957 */
958RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int16_t *pi16)
959{
960 int64_t i64;
961 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64);
962 if (RT_SUCCESS(rc))
963 {
964 int16_t i16 = (int16_t)i64;
965 if (i64 != (int64_t)i16)
966 rc = VWRN_NUMBER_TOO_BIG;
967 }
968 if (pi16)
969 *pi16 = (int16_t)i64;
970 return rc;
971}
972RT_EXPORT_SYMBOL(RTStrToInt16Ex);
973
974
975/**
976 * Converts a string representation of a number to a 16-bit signed number,
977 * making sure the full string is converted.
978 *
979 * @returns iprt status code.
980 * Warnings are used to indicate conversion problems.
981 * @retval VWRN_NUMBER_TOO_BIG
982 * @retval VINF_SUCCESS
983 * @retval VERR_TRAILING_CHARS
984 * @retval VERR_TRAILING_SPACES
985 * @retval VERR_NO_DIGITS
986 *
987 * @param pszValue Pointer to the string value.
988 * @param uBaseAndMaxLen The low byte is the base of the representation, the
989 * upper 24 bits are the max length to parse. If the base
990 * is zero the function will look for known prefixes before
991 * defaulting to 10. A max length of zero means no length
992 * restriction.
993 * @param pi16 Where to store the converted number. (optional)
994 */
995RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, int16_t *pi16)
996{
997 int64_t i64;
998 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64);
999 if (RT_SUCCESS(rc))
1000 {
1001 int16_t i16 = (int16_t)i64;
1002 if (i64 != (int64_t)i16)
1003 rc = VWRN_NUMBER_TOO_BIG;
1004 }
1005 if (pi16)
1006 *pi16 = (int16_t)i64;
1007 return rc;
1008}
1009RT_EXPORT_SYMBOL(RTStrToInt16Full);
1010
1011
1012/**
1013 * Converts a string representation of a number to a 16-bit signed number.
1014 * The base is guessed.
1015 *
1016 * @returns 16-bit signed number on success.
1017 * @returns 0 on failure.
1018 * @param pszValue Pointer to the string value.
1019 */
1020RTDECL(int16_t) RTStrToInt16(const char *pszValue)
1021{
1022 int16_t i16;
1023 int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
1024 if (RT_SUCCESS(rc))
1025 return i16;
1026 return 0;
1027}
1028RT_EXPORT_SYMBOL(RTStrToInt16);
1029
1030
1031/**
1032 * Converts a string representation of a number to a 8-bit signed number.
1033 *
1034 * @returns iprt status code.
1035 * Warnings are used to indicate conversion problems.
1036 * @retval VWRN_NUMBER_TOO_BIG
1037 * @retval VWRN_TRAILING_CHARS
1038 * @retval VWRN_TRAILING_SPACES
1039 * @retval VINF_SUCCESS
1040 * @retval VERR_NO_DIGITS
1041 *
1042 * @param pszValue Pointer to the string value.
1043 * @param ppszNext Where to store the pointer to the first char
1044 * following the number. (Optional)
1045 * @param uBaseAndMaxLen The low byte is the base of the representation, the
1046 * upper 24 bits are the max length to parse. If the base
1047 * is zero the function will look for known prefixes before
1048 * defaulting to 10. A max length of zero means no length
1049 * restriction.
1050 * @param pi8 Where to store the converted number. (optional)
1051 */
1052RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int8_t *pi8)
1053{
1054 int64_t i64;
1055 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64);
1056 if (RT_SUCCESS(rc))
1057 {
1058 int8_t i8 = (int8_t)i64;
1059 if (i64 != (int64_t)i8)
1060 rc = VWRN_NUMBER_TOO_BIG;
1061 }
1062 if (pi8)
1063 *pi8 = (int8_t)i64;
1064 return rc;
1065}
1066RT_EXPORT_SYMBOL(RTStrToInt8Ex);
1067
1068
1069/**
1070 * Converts a string representation of a number to a 8-bit signed number,
1071 * making sure the full string is converted.
1072 *
1073 * @returns iprt status code.
1074 * Warnings are used to indicate conversion problems.
1075 * @retval VWRN_NUMBER_TOO_BIG
1076 * @retval VINF_SUCCESS
1077 * @retval VERR_TRAILING_CHARS
1078 * @retval VERR_TRAILING_SPACES
1079 * @retval VERR_NO_DIGITS
1080 *
1081 * @param pszValue Pointer to the string value.
1082 * @param uBaseAndMaxLen The low byte is the base of the representation, the
1083 * upper 24 bits are the max length to parse. If the base
1084 * is zero the function will look for known prefixes before
1085 * defaulting to 10. A max length of zero means no length
1086 * restriction.
1087 * @param pi8 Where to store the converted number. (optional)
1088 */
1089RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, int8_t *pi8)
1090{
1091 int64_t i64;
1092 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64);
1093 if (RT_SUCCESS(rc))
1094 {
1095 int8_t i8 = (int8_t)i64;
1096 if (i64 != (int64_t)i8)
1097 rc = VWRN_NUMBER_TOO_BIG;
1098 }
1099 if (pi8)
1100 *pi8 = (int8_t)i64;
1101 return rc;
1102}
1103RT_EXPORT_SYMBOL(RTStrToInt8Full);
1104
1105
1106/**
1107 * Converts a string representation of a number to a 8-bit signed number.
1108 * The base is guessed.
1109 *
1110 * @returns 8-bit signed number on success.
1111 * @returns 0 on failure.
1112 * @param pszValue Pointer to the string value.
1113 */
1114RTDECL(int8_t) RTStrToInt8(const char *pszValue)
1115{
1116 int8_t i8;
1117 int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
1118 if (RT_SUCCESS(rc))
1119 return i8;
1120 return 0;
1121}
1122RT_EXPORT_SYMBOL(RTStrToInt8);
1123
1124
1125RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags,
1126 const char **ppszNext, size_t *pcbReturned)
1127{
1128 size_t cbDst = cb;
1129 uint8_t *pbDst = (uint8_t *)pv;
1130 const unsigned char *pszSrc = (const unsigned char *)pszHex;
1131 unsigned char uchDigit;
1132
1133 if (pcbReturned)
1134 *pcbReturned = 0;
1135 if (ppszNext)
1136 *ppszNext = NULL;
1137 AssertPtrReturn(pszHex, VERR_INVALID_POINTER);
1138 AssertReturn(!(fFlags & ~RTSTRCONVERTHEXBYTES_F_SEP_COLON), VERR_INVALID_FLAGS);
1139
1140 if (fFlags & RTSTRCONVERTHEXBYTES_F_SEP_COLON)
1141 {
1142 /*
1143 * Optional colon separators.
1144 */
1145 bool fPrevColon = true; /* leading colon is taken to mean leading zero byte */
1146 for (;;)
1147 {
1148 /* Pick the next two digit from the string. */
1149 uchDigit = g_auchDigits[*pszSrc++];
1150 if (uchDigit >= 16)
1151 {
1152 if (uchDigit == 253 /* colon */)
1153 {
1154 Assert(pszSrc[-1] == ':');
1155 if (!fPrevColon)
1156 fPrevColon = true;
1157 /* Add zero byte if there is room. */
1158 else if (cbDst > 0)
1159 {
1160 cbDst--;
1161 *pbDst++ = 0;
1162 }
1163 else
1164 {
1165 if (pcbReturned)
1166 *pcbReturned = pbDst - (uint8_t *)pv;
1167 if (ppszNext)
1168 *ppszNext = (const char *)pszSrc - 1;
1169 return VERR_BUFFER_OVERFLOW;
1170 }
1171 continue;
1172 }
1173 else
1174 break;
1175 }
1176 else
1177 {
1178 /* Got one digit, check what comes next: */
1179 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1180 if (uchDigit2 < 16)
1181 {
1182 if (cbDst > 0)
1183 {
1184 *pbDst++ = (uchDigit << 4) | uchDigit2;
1185 cbDst--;
1186 fPrevColon = false;
1187 }
1188 else
1189 {
1190 if (pcbReturned)
1191 *pcbReturned = pbDst - (uint8_t *)pv;
1192 if (ppszNext)
1193 *ppszNext = (const char *)pszSrc - 1;
1194 return VERR_BUFFER_OVERFLOW;
1195 }
1196 }
1197 /* Lone digits are only allowed if following a colon or at the very start, because
1198 if there is more than one byte it ambigious whether it is the lead or tail byte
1199 that only has one digit in it.
1200 Note! This also ensures better compatibility with the no-separator variant
1201 (except for single digit strings, which are accepted here but not below). */
1202 else if (fPrevColon)
1203 {
1204 if (cbDst > 0)
1205 {
1206 *pbDst++ = uchDigit;
1207 cbDst--;
1208 }
1209 else
1210 {
1211 if (pcbReturned)
1212 *pcbReturned = pbDst - (uint8_t *)pv;
1213 if (ppszNext)
1214 *ppszNext = (const char *)pszSrc - 1;
1215 return VERR_BUFFER_OVERFLOW;
1216 }
1217 if (uchDigit2 == 253 /* colon */)
1218 {
1219 Assert(pszSrc[-1] == ':');
1220 fPrevColon = true;
1221 }
1222 else
1223 {
1224 fPrevColon = false;
1225 uchDigit = uchDigit2;
1226 break;
1227 }
1228 }
1229 else
1230 {
1231 if (pcbReturned)
1232 *pcbReturned = pbDst - (uint8_t *)pv;
1233 if (ppszNext)
1234 *ppszNext = (const char *)pszSrc - 2;
1235 return VERR_UNEVEN_INPUT;
1236 }
1237 }
1238 }
1239
1240 /* Trailing colon means trailing zero byte: */
1241 if (fPrevColon)
1242 {
1243 if (cbDst > 0)
1244 {
1245 *pbDst++ = 0;
1246 cbDst--;
1247 }
1248 else
1249 {
1250 if (pcbReturned)
1251 *pcbReturned = pbDst - (uint8_t *)pv;
1252 if (ppszNext)
1253 *ppszNext = (const char *)pszSrc - 1;
1254 return VERR_BUFFER_OVERFLOW;
1255 }
1256 }
1257 }
1258 else
1259 {
1260 /*
1261 * No separators.
1262 */
1263 for (;;)
1264 {
1265 /* Pick the next two digit from the string. */
1266 uchDigit = g_auchDigits[*pszSrc++];
1267 if (uchDigit < 16)
1268 {
1269 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1270 if (uchDigit2 < 16)
1271 {
1272 /* Add the byte to the output buffer. */
1273 if (cbDst)
1274 {
1275 cbDst--;
1276 *pbDst++ = (uchDigit << 4) | uchDigit2;
1277 }
1278 else
1279 {
1280 if (pcbReturned)
1281 *pcbReturned = pbDst - (uint8_t *)pv;
1282 if (ppszNext)
1283 *ppszNext = (const char *)pszSrc - 2;
1284 return VERR_BUFFER_OVERFLOW;
1285 }
1286 }
1287 else
1288 {
1289 if (pcbReturned)
1290 *pcbReturned = pbDst - (uint8_t *)pv;
1291 if (ppszNext)
1292 *ppszNext = (const char *)pszSrc - 2;
1293 return VERR_UNEVEN_INPUT;
1294 }
1295 }
1296 else
1297 break;
1298 }
1299 }
1300
1301 /*
1302 * End of hex bytes, look what comes next and figure out what to return.
1303 */
1304 if (pcbReturned)
1305 *pcbReturned = pbDst - (uint8_t *)pv;
1306 if (ppszNext)
1307 *ppszNext = (const char *)pszSrc - 1;
1308
1309 if (uchDigit == 254)
1310 {
1311 Assert(pszSrc[-1] == '\0');
1312 if (cbDst == 0)
1313 return VINF_SUCCESS;
1314 return pcbReturned ? VINF_BUFFER_UNDERFLOW : VERR_BUFFER_UNDERFLOW;
1315 }
1316 Assert(pszSrc[-1] != '\0');
1317
1318 if (cbDst != 0 && !pcbReturned)
1319 return VERR_BUFFER_UNDERFLOW;
1320
1321 while (uchDigit == 252)
1322 {
1323 Assert(pszSrc[-1] == ' ' || pszSrc[-1] == '\t');
1324 uchDigit = g_auchDigits[*pszSrc++];
1325 }
1326
1327 Assert(pszSrc[-1] == '\0' ? uchDigit == 254 : uchDigit != 254);
1328 return uchDigit == 254 ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
1329
1330}
1331RT_EXPORT_SYMBOL(RTStrConvertHexBytesEx);
1332
1333
1334RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags)
1335{
1336 return RTStrConvertHexBytesEx(pszHex, pv, cb, fFlags, NULL /*ppszNext*/, NULL /*pcbReturned*/);
1337
1338}
1339RT_EXPORT_SYMBOL(RTStrConvertHexBytes);
1340
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette