VirtualBox

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

Last change on this file since 93103 was 86378, checked in by vboxsync, 4 years ago

IPRT/RTStrToInt64Ex: Shut up tstRTCRest-1 asan warning reading INT64_MIN. bugref:9841

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