VirtualBox

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

Last change on this file since 96158 was 96156, checked in by vboxsync, 3 years ago

IPRT: Added RTStrToFloat, RTStrToDouble and RTStrToLongDouble. Still some rought edges; only tested on Windows. [build fixes] bugref:10261

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

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