VirtualBox

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

Last change on this file since 81106 was 79562, checked in by vboxsync, 5 years ago

IPRT: Added RTSTRCONVERTHEXBYTES_F_SEP_COLON as well as a RTStrConvertHexBytesEx variant. bugref:9288

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 36.0 KB
Line 
1/* $Id: strtonum.cpp 79562 2019-07-05 20:37:19Z vboxsync $ */
2/** @file
3 * IPRT - String To Number Conversion.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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 if ( !(u64 & RT_BIT_64(63))
637 || (!fPositive && u64 == RT_BIT_64(63)) )
638 { /* likely */ }
639 else
640 rc = VWRN_NUMBER_TOO_BIG;
641
642 if (pi64)
643 *pi64 = fPositive ? u64 : -(int64_t)u64;
644
645 if (psz == pszValue)
646 rc = VERR_NO_DIGITS;
647
648 if (ppszNext)
649 *ppszNext = (char *)psz;
650
651 /*
652 * Warn about trailing chars/spaces.
653 */
654 if ( rc == VINF_SUCCESS
655 && *psz)
656 {
657 while (*psz == ' ' || *psz == '\t')
658 psz++;
659 rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
660 }
661
662 return rc;
663}
664RT_EXPORT_SYMBOL(RTStrToInt64Ex);
665
666
667/**
668 * Converts a string representation of a number to a 64-bit signed number,
669 * making sure the full string is converted.
670 *
671 * @returns iprt status code.
672 * Warnings are used to indicate conversion problems.
673 * @retval VWRN_NUMBER_TOO_BIG
674 * @retval VINF_SUCCESS
675 * @retval VERR_TRAILING_CHARS
676 * @retval VERR_TRAILING_SPACES
677 * @retval VERR_NO_DIGITS
678 *
679 * @param pszValue Pointer to the string value.
680 * @param uBase The base of the representation used.
681 * If the function will look for known prefixes before defaulting to 10.
682 * @param pi64 Where to store the converted number. (optional)
683 */
684RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64)
685{
686 char *psz;
687 int rc = RTStrToInt64Ex(pszValue, &psz, uBase, pi64);
688 if (RT_SUCCESS(rc) && *psz)
689 {
690 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
691 rc = -rc;
692 else
693 {
694 while (*psz == ' ' || *psz == '\t')
695 psz++;
696 rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
697 }
698 }
699 return rc;
700}
701RT_EXPORT_SYMBOL(RTStrToInt64Full);
702
703
704/**
705 * Converts a string representation of a number to a 64-bit signed number.
706 * The base is guessed.
707 *
708 * @returns 64-bit signed number on success.
709 * @returns 0 on failure.
710 * @param pszValue Pointer to the string value.
711 */
712RTDECL(int64_t) RTStrToInt64(const char *pszValue)
713{
714 int64_t i64;
715 int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
716 if (RT_SUCCESS(rc))
717 return i64;
718 return 0;
719}
720RT_EXPORT_SYMBOL(RTStrToInt64);
721
722
723/**
724 * Converts a string representation of a number to a 32-bit signed number.
725 *
726 * @returns iprt status code.
727 * Warnings are used to indicate conversion problems.
728 * @retval VWRN_NUMBER_TOO_BIG
729 * @retval VWRN_TRAILING_CHARS
730 * @retval VWRN_TRAILING_SPACES
731 * @retval VINF_SUCCESS
732 * @retval VERR_NO_DIGITS
733 *
734 * @param pszValue Pointer to the string value.
735 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
736 * @param uBase The base of the representation used.
737 * If the function will look for known prefixes before defaulting to 10.
738 * @param pi32 Where to store the converted number. (optional)
739 */
740RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32)
741{
742 int64_t i64;
743 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
744 if (RT_SUCCESS(rc))
745 {
746 int32_t i32 = (int32_t)i64;
747 if (i64 != (int64_t)i32)
748 rc = VWRN_NUMBER_TOO_BIG;
749 }
750 if (pi32)
751 *pi32 = (int32_t)i64;
752 return rc;
753}
754RT_EXPORT_SYMBOL(RTStrToInt32Ex);
755
756
757/**
758 * Converts a string representation of a number to a 32-bit signed number,
759 * making sure the full string is converted.
760 *
761 * @returns iprt status code.
762 * Warnings are used to indicate conversion problems.
763 * @retval VWRN_NUMBER_TOO_BIG
764 * @retval VINF_SUCCESS
765 * @retval VERR_TRAILING_CHARS
766 * @retval VERR_TRAILING_SPACES
767 * @retval VERR_NO_DIGITS
768 *
769 * @param pszValue Pointer to the string value.
770 * @param uBase The base of the representation used.
771 * If the function will look for known prefixes before defaulting to 10.
772 * @param pi32 Where to store the converted number. (optional)
773 */
774RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32)
775{
776 int64_t i64;
777 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
778 if (RT_SUCCESS(rc))
779 {
780 int32_t i32 = (int32_t)i64;
781 if (i64 != (int64_t)i32)
782 rc = VWRN_NUMBER_TOO_BIG;
783 }
784 if (pi32)
785 *pi32 = (int32_t)i64;
786 return rc;
787}
788RT_EXPORT_SYMBOL(RTStrToInt32Full);
789
790
791/**
792 * Converts a string representation of a number to a 32-bit signed number.
793 * The base is guessed.
794 *
795 * @returns 32-bit signed number on success.
796 * @returns 0 on failure.
797 * @param pszValue Pointer to the string value.
798 */
799RTDECL(int32_t) RTStrToInt32(const char *pszValue)
800{
801 int32_t i32;
802 int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
803 if (RT_SUCCESS(rc))
804 return i32;
805 return 0;
806}
807RT_EXPORT_SYMBOL(RTStrToInt32);
808
809
810/**
811 * Converts a string representation of a number to a 16-bit signed number.
812 *
813 * @returns iprt status code.
814 * Warnings are used to indicate conversion problems.
815 * @retval VWRN_NUMBER_TOO_BIG
816 * @retval VWRN_TRAILING_CHARS
817 * @retval VWRN_TRAILING_SPACES
818 * @retval VINF_SUCCESS
819 * @retval VERR_NO_DIGITS
820 *
821 * @param pszValue Pointer to the string value.
822 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
823 * @param uBase The base of the representation used.
824 * If the function will look for known prefixes before defaulting to 10.
825 * @param pi16 Where to store the converted number. (optional)
826 */
827RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16)
828{
829 int64_t i64;
830 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
831 if (RT_SUCCESS(rc))
832 {
833 int16_t i16 = (int16_t)i64;
834 if (i64 != (int64_t)i16)
835 rc = VWRN_NUMBER_TOO_BIG;
836 }
837 if (pi16)
838 *pi16 = (int16_t)i64;
839 return rc;
840}
841RT_EXPORT_SYMBOL(RTStrToInt16Ex);
842
843
844/**
845 * Converts a string representation of a number to a 16-bit signed number,
846 * making sure the full string is converted.
847 *
848 * @returns iprt status code.
849 * Warnings are used to indicate conversion problems.
850 * @retval VWRN_NUMBER_TOO_BIG
851 * @retval VINF_SUCCESS
852 * @retval VERR_TRAILING_CHARS
853 * @retval VERR_TRAILING_SPACES
854 * @retval VERR_NO_DIGITS
855 *
856 * @param pszValue Pointer to the string value.
857 * @param uBase The base of the representation used.
858 * If the function will look for known prefixes before defaulting to 10.
859 * @param pi16 Where to store the converted number. (optional)
860 */
861RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16)
862{
863 int64_t i64;
864 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
865 if (RT_SUCCESS(rc))
866 {
867 int16_t i16 = (int16_t)i64;
868 if (i64 != (int64_t)i16)
869 rc = VWRN_NUMBER_TOO_BIG;
870 }
871 if (pi16)
872 *pi16 = (int16_t)i64;
873 return rc;
874}
875RT_EXPORT_SYMBOL(RTStrToInt16Full);
876
877
878/**
879 * Converts a string representation of a number to a 16-bit signed number.
880 * The base is guessed.
881 *
882 * @returns 16-bit signed number on success.
883 * @returns 0 on failure.
884 * @param pszValue Pointer to the string value.
885 */
886RTDECL(int16_t) RTStrToInt16(const char *pszValue)
887{
888 int16_t i16;
889 int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
890 if (RT_SUCCESS(rc))
891 return i16;
892 return 0;
893}
894RT_EXPORT_SYMBOL(RTStrToInt16);
895
896
897/**
898 * Converts a string representation of a number to a 8-bit signed number.
899 *
900 * @returns iprt status code.
901 * Warnings are used to indicate conversion problems.
902 * @retval VWRN_NUMBER_TOO_BIG
903 * @retval VWRN_TRAILING_CHARS
904 * @retval VWRN_TRAILING_SPACES
905 * @retval VINF_SUCCESS
906 * @retval VERR_NO_DIGITS
907 *
908 * @param pszValue Pointer to the string value.
909 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
910 * @param uBase The base of the representation used.
911 * If the function will look for known prefixes before defaulting to 10.
912 * @param pi8 Where to store the converted number. (optional)
913 */
914RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8)
915{
916 int64_t i64;
917 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
918 if (RT_SUCCESS(rc))
919 {
920 int8_t i8 = (int8_t)i64;
921 if (i64 != (int64_t)i8)
922 rc = VWRN_NUMBER_TOO_BIG;
923 }
924 if (pi8)
925 *pi8 = (int8_t)i64;
926 return rc;
927}
928RT_EXPORT_SYMBOL(RTStrToInt8Ex);
929
930
931/**
932 * Converts a string representation of a number to a 8-bit signed number,
933 * making sure the full string is converted.
934 *
935 * @returns iprt status code.
936 * Warnings are used to indicate conversion problems.
937 * @retval VWRN_NUMBER_TOO_BIG
938 * @retval VINF_SUCCESS
939 * @retval VERR_TRAILING_CHARS
940 * @retval VERR_TRAILING_SPACES
941 * @retval VERR_NO_DIGITS
942 *
943 * @param pszValue Pointer to the string value.
944 * @param uBase The base of the representation used.
945 * If the function will look for known prefixes before defaulting to 10.
946 * @param pi8 Where to store the converted number. (optional)
947 */
948RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8)
949{
950 int64_t i64;
951 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
952 if (RT_SUCCESS(rc))
953 {
954 int8_t i8 = (int8_t)i64;
955 if (i64 != (int64_t)i8)
956 rc = VWRN_NUMBER_TOO_BIG;
957 }
958 if (pi8)
959 *pi8 = (int8_t)i64;
960 return rc;
961}
962RT_EXPORT_SYMBOL(RTStrToInt8Full);
963
964
965/**
966 * Converts a string representation of a number to a 8-bit signed number.
967 * The base is guessed.
968 *
969 * @returns 8-bit signed number on success.
970 * @returns 0 on failure.
971 * @param pszValue Pointer to the string value.
972 */
973RTDECL(int8_t) RTStrToInt8(const char *pszValue)
974{
975 int8_t i8;
976 int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
977 if (RT_SUCCESS(rc))
978 return i8;
979 return 0;
980}
981RT_EXPORT_SYMBOL(RTStrToInt8);
982
983
984RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags,
985 const char **ppszNext, size_t *pcbReturned)
986{
987 size_t cbDst = cb;
988 uint8_t *pbDst = (uint8_t *)pv;
989 const unsigned char *pszSrc = (const unsigned char *)pszHex;
990 unsigned char uchDigit;
991
992 if (pcbReturned)
993 *pcbReturned = 0;
994 if (ppszNext)
995 *ppszNext = NULL;
996 AssertPtrReturn(pszHex, VERR_INVALID_POINTER);
997 AssertReturn(!(fFlags & ~RTSTRCONVERTHEXBYTES_F_SEP_COLON), VERR_INVALID_FLAGS);
998
999 if (fFlags & RTSTRCONVERTHEXBYTES_F_SEP_COLON)
1000 {
1001 /*
1002 * Optional colon separators.
1003 */
1004 bool fPrevColon = true; /* leading colon is taken to mean leading zero byte */
1005 for (;;)
1006 {
1007 /* Pick the next two digit from the string. */
1008 uchDigit = g_auchDigits[*pszSrc++];
1009 if (uchDigit >= 16)
1010 {
1011 if (uchDigit == 253 /* colon */)
1012 {
1013 Assert(pszSrc[-1] == ':');
1014 if (!fPrevColon)
1015 fPrevColon = true;
1016 /* Add zero byte if there is room. */
1017 else if (cbDst > 0)
1018 {
1019 cbDst--;
1020 *pbDst++ = 0;
1021 }
1022 else
1023 {
1024 if (pcbReturned)
1025 *pcbReturned = pbDst - (uint8_t *)pv;
1026 if (ppszNext)
1027 *ppszNext = (const char *)pszSrc - 1;
1028 return VERR_BUFFER_OVERFLOW;
1029 }
1030 continue;
1031 }
1032 else
1033 break;
1034 }
1035 else
1036 {
1037 /* Got one digit, check what comes next: */
1038 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1039 if (uchDigit2 < 16)
1040 {
1041 if (cbDst > 0)
1042 {
1043 *pbDst++ = (uchDigit << 4) | uchDigit2;
1044 cbDst--;
1045 fPrevColon = false;
1046 }
1047 else
1048 {
1049 if (pcbReturned)
1050 *pcbReturned = pbDst - (uint8_t *)pv;
1051 if (ppszNext)
1052 *ppszNext = (const char *)pszSrc - 1;
1053 return VERR_BUFFER_OVERFLOW;
1054 }
1055 }
1056 /* Lone digits are only allowed if following a colon or at the very start, because
1057 if there is more than one byte it ambigious whether it is the lead or tail byte
1058 that only has one digit in it.
1059 Note! This also ensures better compatibility with the no-separator variant
1060 (except for single digit strings, which are accepted here but not below). */
1061 else if (fPrevColon)
1062 {
1063 if (cbDst > 0)
1064 {
1065 *pbDst++ = uchDigit;
1066 cbDst--;
1067 }
1068 else
1069 {
1070 if (pcbReturned)
1071 *pcbReturned = pbDst - (uint8_t *)pv;
1072 if (ppszNext)
1073 *ppszNext = (const char *)pszSrc - 1;
1074 return VERR_BUFFER_OVERFLOW;
1075 }
1076 if (uchDigit2 == 253 /* colon */)
1077 {
1078 Assert(pszSrc[-1] == ':');
1079 fPrevColon = true;
1080 }
1081 else
1082 {
1083 fPrevColon = false;
1084 uchDigit = uchDigit2;
1085 break;
1086 }
1087 }
1088 else
1089 {
1090 if (pcbReturned)
1091 *pcbReturned = pbDst - (uint8_t *)pv;
1092 if (ppszNext)
1093 *ppszNext = (const char *)pszSrc - 2;
1094 return VERR_UNEVEN_INPUT;
1095 }
1096 }
1097 }
1098
1099 /* Trailing colon means trailing zero byte: */
1100 if (fPrevColon)
1101 {
1102 if (cbDst > 0)
1103 {
1104 *pbDst++ = 0;
1105 cbDst--;
1106 }
1107 else
1108 {
1109 if (pcbReturned)
1110 *pcbReturned = pbDst - (uint8_t *)pv;
1111 if (ppszNext)
1112 *ppszNext = (const char *)pszSrc - 1;
1113 return VERR_BUFFER_OVERFLOW;
1114 }
1115 }
1116 }
1117 else
1118 {
1119 /*
1120 * No separators.
1121 */
1122 for (;;)
1123 {
1124 /* Pick the next two digit from the string. */
1125 uchDigit = g_auchDigits[*pszSrc++];
1126 if (uchDigit < 16)
1127 {
1128 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++];
1129 if (uchDigit2 < 16)
1130 {
1131 /* Add the byte to the output buffer. */
1132 if (cbDst)
1133 {
1134 cbDst--;
1135 *pbDst++ = (uchDigit << 4) | uchDigit2;
1136 }
1137 else
1138 {
1139 if (pcbReturned)
1140 *pcbReturned = pbDst - (uint8_t *)pv;
1141 if (ppszNext)
1142 *ppszNext = (const char *)pszSrc - 2;
1143 return VERR_BUFFER_OVERFLOW;
1144 }
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_UNEVEN_INPUT;
1153 }
1154 }
1155 else
1156 break;
1157 }
1158 }
1159
1160 /*
1161 * End of hex bytes, look what comes next and figure out what to return.
1162 */
1163 if (pcbReturned)
1164 *pcbReturned = pbDst - (uint8_t *)pv;
1165 if (ppszNext)
1166 *ppszNext = (const char *)pszSrc - 1;
1167
1168 if (uchDigit == 254)
1169 {
1170 Assert(pszSrc[-1] == '\0');
1171 if (cbDst == 0)
1172 return VINF_SUCCESS;
1173 return pcbReturned ? VINF_BUFFER_UNDERFLOW : VERR_BUFFER_UNDERFLOW;
1174 }
1175 Assert(pszSrc[-1] != '\0');
1176
1177 if (cbDst != 0 && !pcbReturned)
1178 return VERR_BUFFER_UNDERFLOW;
1179
1180 while (uchDigit == 252)
1181 {
1182 Assert(pszSrc[-1] == ' ' || pszSrc[-1] == '\t');
1183 uchDigit = g_auchDigits[*pszSrc++];
1184 }
1185
1186 Assert(pszSrc[-1] == '\0' ? uchDigit == 254 : uchDigit != 254);
1187 return uchDigit == 254 ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
1188
1189}
1190RT_EXPORT_SYMBOL(RTStrConvertHexBytesEx);
1191
1192
1193RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags)
1194{
1195 return RTStrConvertHexBytesEx(pszHex, pv, cb, fFlags, NULL /*ppszNext*/, NULL /*pcbReturned*/);
1196
1197}
1198RT_EXPORT_SYMBOL(RTStrConvertHexBytes);
1199
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