VirtualBox

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

Last change on this file since 96186 was 96170, checked in by vboxsync, 3 years ago

IPRT: Doxygen fixes in strtonum.cpp and strtofloat.cpp. bugref:20261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 42.6 KB
Line 
1/* $Id: strtonum.cpp 96170 2022-08-12 12:23:56Z 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 pi16 Where to store the converted number. (optional)
947 */
948RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int16_t *pi16)
949{
950 int64_t i64;
951 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64);
952 if (RT_SUCCESS(rc))
953 {
954 int16_t i16 = (int16_t)i64;
955 if (i64 != (int64_t)i16)
956 rc = VWRN_NUMBER_TOO_BIG;
957 }
958 if (pi16)
959 *pi16 = (int16_t)i64;
960 return rc;
961}
962RT_EXPORT_SYMBOL(RTStrToInt16Ex);
963
964
965/**
966 * Converts a string representation of a number to a 16-bit signed number,
967 * making sure the full string is converted.
968 *
969 * @returns iprt status code.
970 * Warnings are used to indicate conversion problems.
971 * @retval VWRN_NUMBER_TOO_BIG
972 * @retval VINF_SUCCESS
973 * @retval VERR_TRAILING_CHARS
974 * @retval VERR_TRAILING_SPACES
975 * @retval VERR_NO_DIGITS
976 *
977 * @param pszValue Pointer to the string value.
978 * @param uBaseAndMaxLen The low byte is the base of the representation, the
979 * upper 24 bits are the max length to parse. If the base
980 * is zero the function will look for known prefixes before
981 * defaulting to 10. A max length of zero means no length
982 * restriction.
983 * @param pi16 Where to store the converted number. (optional)
984 */
985RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, int16_t *pi16)
986{
987 int64_t i64;
988 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64);
989 if (RT_SUCCESS(rc))
990 {
991 int16_t i16 = (int16_t)i64;
992 if (i64 != (int64_t)i16)
993 rc = VWRN_NUMBER_TOO_BIG;
994 }
995 if (pi16)
996 *pi16 = (int16_t)i64;
997 return rc;
998}
999RT_EXPORT_SYMBOL(RTStrToInt16Full);
1000
1001
1002/**
1003 * Converts a string representation of a number to a 16-bit signed number.
1004 * The base is guessed.
1005 *
1006 * @returns 16-bit signed number on success.
1007 * @returns 0 on failure.
1008 * @param pszValue Pointer to the string value.
1009 */
1010RTDECL(int16_t) RTStrToInt16(const char *pszValue)
1011{
1012 int16_t i16;
1013 int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
1014 if (RT_SUCCESS(rc))
1015 return i16;
1016 return 0;
1017}
1018RT_EXPORT_SYMBOL(RTStrToInt16);
1019
1020
1021/**
1022 * Converts a string representation of a number to a 8-bit signed number.
1023 *
1024 * @returns iprt status code.
1025 * Warnings are used to indicate conversion problems.
1026 * @retval VWRN_NUMBER_TOO_BIG
1027 * @retval VWRN_TRAILING_CHARS
1028 * @retval VWRN_TRAILING_SPACES
1029 * @retval VINF_SUCCESS
1030 * @retval VERR_NO_DIGITS
1031 *
1032 * @param pszValue Pointer to the string value.
1033 * @param ppszNext Where to store the pointer to the first char
1034 * following the number. (Optional)
1035 * @param uBaseAndMaxLen The low byte is the base of the representation, the
1036 * upper 24 bits are the max length to parse. If the base
1037 * is zero the function will look for known prefixes before
1038 * defaulting to 10. A max length of zero means no length
1039 * restriction.
1040 * @param pi8 Where to store the converted number. (optional)
1041 */
1042RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int8_t *pi8)
1043{
1044 int64_t i64;
1045 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64);
1046 if (RT_SUCCESS(rc))
1047 {
1048 int8_t i8 = (int8_t)i64;
1049 if (i64 != (int64_t)i8)
1050 rc = VWRN_NUMBER_TOO_BIG;
1051 }
1052 if (pi8)
1053 *pi8 = (int8_t)i64;
1054 return rc;
1055}
1056RT_EXPORT_SYMBOL(RTStrToInt8Ex);
1057
1058
1059/**
1060 * Converts a string representation of a number to a 8-bit signed number,
1061 * making sure the full string is converted.
1062 *
1063 * @returns iprt status code.
1064 * Warnings are used to indicate conversion problems.
1065 * @retval VWRN_NUMBER_TOO_BIG
1066 * @retval VINF_SUCCESS
1067 * @retval VERR_TRAILING_CHARS
1068 * @retval VERR_TRAILING_SPACES
1069 * @retval VERR_NO_DIGITS
1070 *
1071 * @param pszValue Pointer to the string value.
1072 * @param uBaseAndMaxLen The low byte is the base of the representation, the
1073 * upper 24 bits are the max length to parse. If the base
1074 * is zero the function will look for known prefixes before
1075 * defaulting to 10. A max length of zero means no length
1076 * restriction.
1077 * @param pi8 Where to store the converted number. (optional)
1078 */
1079RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, int8_t *pi8)
1080{
1081 int64_t i64;
1082 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64);
1083 if (RT_SUCCESS(rc))
1084 {
1085 int8_t i8 = (int8_t)i64;
1086 if (i64 != (int64_t)i8)
1087 rc = VWRN_NUMBER_TOO_BIG;
1088 }
1089 if (pi8)
1090 *pi8 = (int8_t)i64;
1091 return rc;
1092}
1093RT_EXPORT_SYMBOL(RTStrToInt8Full);
1094
1095
1096/**
1097 * Converts a string representation of a number to a 8-bit signed number.
1098 * The base is guessed.
1099 *
1100 * @returns 8-bit signed number on success.
1101 * @returns 0 on failure.
1102 * @param pszValue Pointer to the string value.
1103 */
1104RTDECL(int8_t) RTStrToInt8(const char *pszValue)
1105{
1106 int8_t i8;
1107 int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
1108 if (RT_SUCCESS(rc))
1109 return i8;
1110 return 0;
1111}
1112RT_EXPORT_SYMBOL(RTStrToInt8);
1113
1114
1115RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags,
1116 const char **ppszNext, size_t *pcbReturned)
1117{
1118 size_t cbDst = cb;
1119 uint8_t *pbDst = (uint8_t *)pv;
1120 const unsigned char *pszSrc = (const unsigned char *)pszHex;
1121 unsigned char uchDigit;
1122
1123 if (pcbReturned)
1124 *pcbReturned = 0;
1125 if (ppszNext)
1126 *ppszNext = NULL;
1127 AssertPtrReturn(pszHex, VERR_INVALID_POINTER);
1128 AssertReturn(!(fFlags & ~RTSTRCONVERTHEXBYTES_F_SEP_COLON), VERR_INVALID_FLAGS);
1129
1130 if (fFlags & RTSTRCONVERTHEXBYTES_F_SEP_COLON)
1131 {
1132 /*
1133 * Optional colon separators.
1134 */
1135 bool fPrevColon = true; /* leading colon is taken to mean leading zero byte */
1136 for (;;)
1137 {
1138 /* Pick the next two digit from the string. */
1139 uchDigit = g_auchDigits[*pszSrc++];
1140 if (uchDigit >= 16)
1141 {
1142 if (uchDigit == 253 /* colon */)
1143 {
1144 Assert(pszSrc[-1] == ':');
1145 if (!fPrevColon)
1146 fPrevColon = true;
1147 /* Add zero byte if there is room. */
1148 else if (cbDst > 0)
1149 {
1150 cbDst--;
1151 *pbDst++ = 0;
1152 }
1153 else
1154 {
1155 if (pcbReturned)
1156 *pcbReturned = pbDst - (uint8_t *)pv;
1157 if (ppszNext)
1158 *ppszNext = (const char *)pszSrc - 1;
1159 return VERR_BUFFER_OVERFLOW;
1160 }
1161 continue;
1162 }
1163 else
1164 break;
1165 }
1166 else
1167 {
1168 /* Got one digit, check what comes next: */
1169 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1170 if (uchDigit2 < 16)
1171 {
1172 if (cbDst > 0)
1173 {
1174 *pbDst++ = (uchDigit << 4) | uchDigit2;
1175 cbDst--;
1176 fPrevColon = false;
1177 }
1178 else
1179 {
1180 if (pcbReturned)
1181 *pcbReturned = pbDst - (uint8_t *)pv;
1182 if (ppszNext)
1183 *ppszNext = (const char *)pszSrc - 1;
1184 return VERR_BUFFER_OVERFLOW;
1185 }
1186 }
1187 /* Lone digits are only allowed if following a colon or at the very start, because
1188 if there is more than one byte it ambigious whether it is the lead or tail byte
1189 that only has one digit in it.
1190 Note! This also ensures better compatibility with the no-separator variant
1191 (except for single digit strings, which are accepted here but not below). */
1192 else if (fPrevColon)
1193 {
1194 if (cbDst > 0)
1195 {
1196 *pbDst++ = uchDigit;
1197 cbDst--;
1198 }
1199 else
1200 {
1201 if (pcbReturned)
1202 *pcbReturned = pbDst - (uint8_t *)pv;
1203 if (ppszNext)
1204 *ppszNext = (const char *)pszSrc - 1;
1205 return VERR_BUFFER_OVERFLOW;
1206 }
1207 if (uchDigit2 == 253 /* colon */)
1208 {
1209 Assert(pszSrc[-1] == ':');
1210 fPrevColon = true;
1211 }
1212 else
1213 {
1214 fPrevColon = false;
1215 uchDigit = uchDigit2;
1216 break;
1217 }
1218 }
1219 else
1220 {
1221 if (pcbReturned)
1222 *pcbReturned = pbDst - (uint8_t *)pv;
1223 if (ppszNext)
1224 *ppszNext = (const char *)pszSrc - 2;
1225 return VERR_UNEVEN_INPUT;
1226 }
1227 }
1228 }
1229
1230 /* Trailing colon means trailing zero byte: */
1231 if (fPrevColon)
1232 {
1233 if (cbDst > 0)
1234 {
1235 *pbDst++ = 0;
1236 cbDst--;
1237 }
1238 else
1239 {
1240 if (pcbReturned)
1241 *pcbReturned = pbDst - (uint8_t *)pv;
1242 if (ppszNext)
1243 *ppszNext = (const char *)pszSrc - 1;
1244 return VERR_BUFFER_OVERFLOW;
1245 }
1246 }
1247 }
1248 else
1249 {
1250 /*
1251 * No separators.
1252 */
1253 for (;;)
1254 {
1255 /* Pick the next two digit from the string. */
1256 uchDigit = g_auchDigits[*pszSrc++];
1257 if (uchDigit < 16)
1258 {
1259 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1260 if (uchDigit2 < 16)
1261 {
1262 /* Add the byte to the output buffer. */
1263 if (cbDst)
1264 {
1265 cbDst--;
1266 *pbDst++ = (uchDigit << 4) | uchDigit2;
1267 }
1268 else
1269 {
1270 if (pcbReturned)
1271 *pcbReturned = pbDst - (uint8_t *)pv;
1272 if (ppszNext)
1273 *ppszNext = (const char *)pszSrc - 2;
1274 return VERR_BUFFER_OVERFLOW;
1275 }
1276 }
1277 else
1278 {
1279 if (pcbReturned)
1280 *pcbReturned = pbDst - (uint8_t *)pv;
1281 if (ppszNext)
1282 *ppszNext = (const char *)pszSrc - 2;
1283 return VERR_UNEVEN_INPUT;
1284 }
1285 }
1286 else
1287 break;
1288 }
1289 }
1290
1291 /*
1292 * End of hex bytes, look what comes next and figure out what to return.
1293 */
1294 if (pcbReturned)
1295 *pcbReturned = pbDst - (uint8_t *)pv;
1296 if (ppszNext)
1297 *ppszNext = (const char *)pszSrc - 1;
1298
1299 if (uchDigit == 254)
1300 {
1301 Assert(pszSrc[-1] == '\0');
1302 if (cbDst == 0)
1303 return VINF_SUCCESS;
1304 return pcbReturned ? VINF_BUFFER_UNDERFLOW : VERR_BUFFER_UNDERFLOW;
1305 }
1306 Assert(pszSrc[-1] != '\0');
1307
1308 if (cbDst != 0 && !pcbReturned)
1309 return VERR_BUFFER_UNDERFLOW;
1310
1311 while (uchDigit == 252)
1312 {
1313 Assert(pszSrc[-1] == ' ' || pszSrc[-1] == '\t');
1314 uchDigit = g_auchDigits[*pszSrc++];
1315 }
1316
1317 Assert(pszSrc[-1] == '\0' ? uchDigit == 254 : uchDigit != 254);
1318 return uchDigit == 254 ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
1319
1320}
1321RT_EXPORT_SYMBOL(RTStrConvertHexBytesEx);
1322
1323
1324RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags)
1325{
1326 return RTStrConvertHexBytesEx(pszHex, pv, cb, fFlags, NULL /*ppszNext*/, NULL /*pcbReturned*/);
1327
1328}
1329RT_EXPORT_SYMBOL(RTStrConvertHexBytes);
1330
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