VirtualBox

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

Last change on this file since 24656 was 24645, checked in by vboxsync, 15 years ago

IPRT: Burn fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 30.3 KB
Line 
1/* $Id: strtonum.cpp 24645 2009-11-13 16:33:57Z vboxsync $ */
2/** @file
3 * IPRT - String To Number Convertion.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/mem.h>
36#include <iprt/string.h>
37#include "internal/iprt.h"
38
39#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
40#include <iprt/err.h>
41
42
43/*******************************************************************************
44* Global Variables *
45*******************************************************************************/
46/** 8-bit char -> digit. */
47static const unsigned char g_auchDigits[256] =
48{
49 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,
50 255,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,255,255,255,255,255,255,
51 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,
52 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,
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 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};
58/** Approximated overflow shift checks. */
59static const char g_auchShift[36] =
60{
61 /* 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 */
62 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
63};
64
65/*
66#include <stdio.h>
67int main()
68{
69 int i;
70 printf("static const unsigned char g_auchDigits[256] =\n"
71 "{");
72 for (i = 0; i < 256; i++)
73 {
74 int ch = 255;
75 if (i >= '0' && i <= '9')
76 ch = i - '0';
77 else if (i >= 'a' && i <= 'z')
78 ch = i - 'a' + 10;
79 else if (i >= 'A' && i <= 'Z')
80 ch = i - 'A' + 10;
81 if (i == 0)
82 printf("\n %3d", ch);
83 else if ((i % 32) == 0)
84 printf(",\n %3d", ch);
85 else
86 printf(",%3d", ch);
87 }
88 printf("\n"
89 "};\n");
90 return 0;
91}
92*/
93
94
95/**
96 * Converts a string representation of a version number to an unsigned number.
97 *
98 * @returns iprt status code.
99 * Warnings are used to indicate convertion problems.
100 * @retval VWRN_NUMBER_TOO_BIG
101 * @retval VWRN_TRAILING_CHARS
102 * @retval VWRN_TRAILING_SPACES
103 * @retval VINF_SUCCESS
104 * @retval VERR_NO_MEMORY
105 * @retval VERR_NO_DIGITS
106 *
107 * @param pszValue Pointer to the string value.
108 * @param pu32 Where to store the converted number.
109 */
110RTDECL(int) RTStrVersionToUInt32(const char *pszVer, uint32_t *pu32)
111{
112 const char *str = pszVer;
113 AssertPtr(pu32);
114 AssertPtr(str);
115
116 char *strNew = (char*)RTMemAllocZ((strlen(pszVer) + 1) * sizeof(char));
117 if (strNew == NULL)
118 return VERR_NO_MEMORY;
119
120 int rc = VERR_NO_DIGITS;
121 uint16_t c = 0;
122 bool fLastInvalid = false;
123 while ( str
124 && *str != '\0')
125 {
126 if (fLastInvalid)
127 {
128 if ( *str == '-'
129 || *str == '_')
130 {
131 fLastInvalid = false;
132 }
133 }
134 else
135 {
136 if (RT_C_IS_DIGIT(*str))
137 {
138 strNew[c++] = *str;
139 }
140 else if ( *str != '.'
141 && c == 0)
142 {
143 fLastInvalid = true;
144 }
145 }
146 str++;
147 }
148 strNew[c] = '\0';
149
150 /* Convert final number string to number */
151 if (fLastInvalid)
152 {
153 *pu32 = 0;
154 rc = VERR_NO_DIGITS;
155 }
156 else
157 {
158 rc = RTStrToUInt32Ex(strNew,
159 NULL, /* Next pointer, not used */
160 10 /* Number base */,
161 pu32);
162 if (rc != VINF_SUCCESS)
163 *pu32 = 0;
164 }
165 RTStrFree(strNew);
166 return rc;
167}
168
169
170/**
171 * Converts a string representation of a number to a 64-bit unsigned number.
172 *
173 * @returns iprt status code.
174 * Warnings are used to indicate convertion problems.
175 * @retval VWRN_NUMBER_TOO_BIG
176 * @retval VWRN_NEGATIVE_UNSIGNED
177 * @retval VWRN_TRAILING_CHARS
178 * @retval VWRN_TRAILING_SPACES
179 * @retval VINF_SUCCESS
180 * @retval VERR_NO_DIGITS
181 *
182 * @param pszValue Pointer to the string value.
183 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
184 * @param uBase The base of the representation used.
185 * If the function will look for known prefixes before defaulting to 10.
186 * @param pu64 Where to store the converted number. (optional)
187 */
188RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64)
189{
190 const char *psz = pszValue;
191 int iShift;
192 int rc;
193 uint64_t u64;
194 unsigned char uch;
195
196 /*
197 * Positive/Negative stuff.
198 */
199 bool fPositive = true;
200 for (;; psz++)
201 {
202 if (*psz == '+')
203 fPositive = true;
204 else if (*psz == '-')
205 fPositive = !fPositive;
206 else
207 break;
208 }
209
210 /*
211 * Check for hex prefix.
212 */
213 if (!uBase)
214 {
215 if ( psz[0] == '0'
216 && (psz[1] == 'x' || psz[1] == 'X')
217 && g_auchDigits[(unsigned char)psz[2]] < 16)
218 {
219 uBase = 16;
220 psz += 2;
221 }
222 else if ( psz[0] == '0'
223 && g_auchDigits[(unsigned char)psz[1]] < 8)
224 {
225 uBase = 8;
226 psz++;
227 }
228 else
229 uBase = 10;
230 }
231 else if ( uBase == 16
232 && psz[0] == '0'
233 && (psz[1] == 'x' || psz[1] == 'X')
234 && g_auchDigits[(unsigned char)psz[2]] < 16)
235 psz += 2;
236
237 /*
238 * Interpret the value.
239 * Note: We only support ascii digits at this time... :-)
240 */
241 iShift = g_auchShift[uBase];
242 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
243 rc = VINF_SUCCESS;
244 u64 = 0;
245 while ((uch = (unsigned char)*psz) != 0)
246 {
247 unsigned char chDigit = g_auchDigits[uch];
248 uint64_t u64Prev;
249
250 if (chDigit >= uBase)
251 break;
252
253 u64Prev = u64;
254 u64 *= uBase;
255 u64 += chDigit;
256 if (u64Prev > u64 || (u64Prev >> iShift))
257 rc = VWRN_NUMBER_TOO_BIG;
258 psz++;
259 }
260
261 if (!fPositive)
262 {
263 if (rc == VINF_SUCCESS)
264 rc = VWRN_NEGATIVE_UNSIGNED;
265 u64 = -(int64_t)u64;
266 }
267
268 if (pu64)
269 *pu64 = u64;
270
271 if (psz == pszValue)
272 rc = VERR_NO_DIGITS;
273
274 if (ppszNext)
275 *ppszNext = (char *)psz;
276
277 /*
278 * Warn about trailing chars/spaces.
279 */
280 if ( rc == VINF_SUCCESS
281 && *psz)
282 {
283 while (*psz == ' ' || *psz == '\t')
284 psz++;
285 rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
286 }
287
288 return rc;
289}
290RT_EXPORT_SYMBOL(RTStrToUInt64Ex);
291
292
293/**
294 * Converts a string representation of a number to a 64-bit unsigned number,
295 * making sure the full string is converted.
296 *
297 * @returns iprt status code.
298 * Warnings are used to indicate convertion problems.
299 * @retval VWRN_NUMBER_TOO_BIG
300 * @retval VWRN_NEGATIVE_UNSIGNED
301 * @retval VINF_SUCCESS
302 * @retval VERR_NO_DIGITS
303 * @retval VERR_TRAILING_SPACES
304 * @retval VERR_TRAILING_CHARS
305 *
306 * @param pszValue Pointer to the string value.
307 * @param uBase The base of the representation used.
308 * If the function will look for known prefixes before defaulting to 10.
309 * @param pu64 Where to store the converted number. (optional)
310 */
311RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64)
312{
313 char *psz;
314 int rc = RTStrToUInt64Ex(pszValue, &psz, uBase, pu64);
315 if (RT_SUCCESS(rc) && *psz)
316 {
317 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
318 rc = -rc;
319 else
320 {
321 while (*psz == ' ' || *psz == '\t')
322 psz++;
323 rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
324 }
325 }
326 return rc;
327}
328RT_EXPORT_SYMBOL(RTStrToUInt64Full);
329
330
331/**
332 * Converts a string representation of a number to a 64-bit unsigned number.
333 * The base is guessed.
334 *
335 * @returns 64-bit unsigned number on success.
336 * @returns 0 on failure.
337 * @param pszValue Pointer to the string value.
338 */
339RTDECL(uint64_t) RTStrToUInt64(const char *pszValue)
340{
341 uint64_t u64;
342 int rc = RTStrToUInt64Ex(pszValue, NULL, 0, &u64);
343 if (RT_SUCCESS(rc))
344 return u64;
345 return 0;
346}
347RT_EXPORT_SYMBOL(RTStrToUInt64);
348
349
350/**
351 * Converts a string representation of a number to a 32-bit unsigned number.
352 *
353 * @returns iprt status code.
354 * Warnings are used to indicate convertion problems.
355 * @retval VWRN_NUMBER_TOO_BIG
356 * @retval VWRN_NEGATIVE_UNSIGNED
357 * @retval VWRN_TRAILING_CHARS
358 * @retval VWRN_TRAILING_SPACES
359 * @retval VINF_SUCCESS
360 * @retval VERR_NO_DIGITS
361 *
362 * @param pszValue Pointer to the string value.
363 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
364 * @param uBase The base of the representation used.
365 * If the function will look for known prefixes before defaulting to 10.
366 * @param pu32 Where to store the converted number. (optional)
367 */
368RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
369{
370 uint64_t u64;
371 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
372 if (RT_SUCCESS(rc))
373 {
374 if (u64 & ~0xffffffffULL)
375 rc = VWRN_NUMBER_TOO_BIG;
376 }
377 if (pu32)
378 *pu32 = (uint32_t)u64;
379 return rc;
380}
381RT_EXPORT_SYMBOL(RTStrToUInt32Ex);
382
383
384/**
385 * Converts a string representation of a number to a 32-bit unsigned number,
386 * making sure the full string is converted.
387 *
388 * @returns iprt status code.
389 * Warnings are used to indicate convertion problems.
390 * @retval VWRN_NUMBER_TOO_BIG
391 * @retval VWRN_NEGATIVE_UNSIGNED
392 * @retval VINF_SUCCESS
393 * @retval VERR_NO_DIGITS
394 * @retval VERR_TRAILING_SPACES
395 * @retval VERR_TRAILING_CHARS
396 *
397 * @param pszValue Pointer to the string value.
398 * @param uBase The base of the representation used.
399 * If the function will look for known prefixes before defaulting to 10.
400 * @param pu32 Where to store the converted number. (optional)
401 */
402RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32)
403{
404 uint64_t u64;
405 int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
406 if (RT_SUCCESS(rc))
407 {
408 if (u64 & ~0xffffffffULL)
409 rc = VWRN_NUMBER_TOO_BIG;
410 }
411 if (pu32)
412 *pu32 = (uint32_t)u64;
413 return rc;
414}
415RT_EXPORT_SYMBOL(RTStrToUInt32Full);
416
417
418/**
419 * Converts a string representation of a number to a 64-bit unsigned number.
420 * The base is guessed.
421 *
422 * @returns 32-bit unsigned number on success.
423 * @returns 0 on failure.
424 * @param pszValue Pointer to the string value.
425 */
426RTDECL(uint32_t) RTStrToUInt32(const char *pszValue)
427{
428 uint32_t u32;
429 int rc = RTStrToUInt32Ex(pszValue, NULL, 0, &u32);
430 if (RT_SUCCESS(rc))
431 return u32;
432 return 0;
433}
434RT_EXPORT_SYMBOL(RTStrToUInt32);
435
436
437/**
438 * Converts a string representation of a number to a 16-bit unsigned number.
439 *
440 * @returns iprt status code.
441 * Warnings are used to indicate convertion problems.
442 * @retval VWRN_NUMBER_TOO_BIG
443 * @retval VWRN_NEGATIVE_UNSIGNED
444 * @retval VWRN_TRAILING_CHARS
445 * @retval VWRN_TRAILING_SPACES
446 * @retval VINF_SUCCESS
447 * @retval VERR_NO_DIGITS
448 *
449 * @param pszValue Pointer to the string value.
450 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
451 * @param uBase The base of the representation used.
452 * If the function will look for known prefixes before defaulting to 10.
453 * @param pu16 Where to store the converted number. (optional)
454 */
455RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16)
456{
457 uint64_t u64;
458 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
459 if (RT_SUCCESS(rc))
460 {
461 if (u64 & ~0xffffULL)
462 rc = VWRN_NUMBER_TOO_BIG;
463 }
464 if (pu16)
465 *pu16 = (uint16_t)u64;
466 return rc;
467}
468RT_EXPORT_SYMBOL(RTStrToUInt16Ex);
469
470
471/**
472 * Converts a string representation of a number to a 16-bit unsigned number,
473 * making sure the full string is converted.
474 *
475 * @returns iprt status code.
476 * Warnings are used to indicate convertion problems.
477 * @retval VWRN_NUMBER_TOO_BIG
478 * @retval VWRN_NEGATIVE_UNSIGNED
479 * @retval VINF_SUCCESS
480 * @retval VERR_NO_DIGITS
481 * @retval VERR_TRAILING_SPACES
482 * @retval VERR_TRAILING_CHARS
483 *
484 * @param pszValue Pointer to the string value.
485 * @param uBase The base of the representation used.
486 * If the function will look for known prefixes before defaulting to 10.
487 * @param pu16 Where to store the converted number. (optional)
488 */
489RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16)
490{
491 uint64_t u64;
492 int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
493 if (RT_SUCCESS(rc))
494 {
495 if (u64 & ~0xffffULL)
496 rc = VWRN_NUMBER_TOO_BIG;
497 }
498 if (pu16)
499 *pu16 = (uint16_t)u64;
500 return rc;
501}
502RT_EXPORT_SYMBOL(RTStrToUInt16Full);
503
504
505/**
506 * Converts a string representation of a number to a 16-bit unsigned number.
507 * The base is guessed.
508 *
509 * @returns 16-bit unsigned number on success.
510 * @returns 0 on failure.
511 * @param pszValue Pointer to the string value.
512 */
513RTDECL(uint16_t) RTStrToUInt16(const char *pszValue)
514{
515 uint16_t u16;
516 int rc = RTStrToUInt16Ex(pszValue, NULL, 0, &u16);
517 if (RT_SUCCESS(rc))
518 return u16;
519 return 0;
520}
521RT_EXPORT_SYMBOL(RTStrToUInt16);
522
523
524/**
525 * Converts a string representation of a number to a 8-bit unsigned number.
526 *
527 * @returns iprt status code.
528 * Warnings are used to indicate convertion problems.
529 * @retval VWRN_NUMBER_TOO_BIG
530 * @retval VWRN_NEGATIVE_UNSIGNED
531 * @retval VWRN_TRAILING_CHARS
532 * @retval VWRN_TRAILING_SPACES
533 * @retval VINF_SUCCESS
534 * @retval VERR_NO_DIGITS
535 *
536 * @param pszValue Pointer to the string value.
537 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
538 * @param uBase The base of the representation used.
539 * If the function will look for known prefixes before defaulting to 10.
540 * @param pu8 Where to store the converted number. (optional)
541 */
542RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8)
543{
544 uint64_t u64;
545 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
546 if (RT_SUCCESS(rc))
547 {
548 if (u64 & ~0xffULL)
549 rc = VWRN_NUMBER_TOO_BIG;
550 }
551 if (pu8)
552 *pu8 = (uint8_t)u64;
553 return rc;
554}
555RT_EXPORT_SYMBOL(RTStrToUInt8Ex);
556
557
558/**
559 * Converts a string representation of a number to a 8-bit unsigned number,
560 * making sure the full string is converted.
561 *
562 * @returns iprt status code.
563 * Warnings are used to indicate convertion problems.
564 * @retval VWRN_NUMBER_TOO_BIG
565 * @retval VWRN_NEGATIVE_UNSIGNED
566 * @retval VINF_SUCCESS
567 * @retval VERR_NO_DIGITS
568 * @retval VERR_TRAILING_SPACES
569 * @retval VERR_TRAILING_CHARS
570 *
571 * @param pszValue Pointer to the string value.
572 * @param uBase The base of the representation used.
573 * If the function will look for known prefixes before defaulting to 10.
574 * @param pu8 Where to store the converted number. (optional)
575 */
576RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8)
577{
578 uint64_t u64;
579 int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
580 if (RT_SUCCESS(rc))
581 {
582 if (u64 & ~0xffULL)
583 rc = VWRN_NUMBER_TOO_BIG;
584 }
585 if (pu8)
586 *pu8 = (uint8_t)u64;
587 return rc;
588}
589RT_EXPORT_SYMBOL(RTStrToUInt8Full);
590
591
592/**
593 * Converts a string representation of a number to a 8-bit unsigned number.
594 * The base is guessed.
595 *
596 * @returns 8-bit unsigned number on success.
597 * @returns 0 on failure.
598 * @param pszValue Pointer to the string value.
599 */
600RTDECL(uint8_t) RTStrToUInt8(const char *pszValue)
601{
602 uint8_t u8;
603 int rc = RTStrToUInt8Ex(pszValue, NULL, 0, &u8);
604 if (RT_SUCCESS(rc))
605 return u8;
606 return 0;
607}
608RT_EXPORT_SYMBOL(RTStrToUInt8);
609
610
611
612
613
614
615
616/**
617 * Converts a string representation of a number to a 64-bit signed number.
618 *
619 * @returns iprt status code.
620 * Warnings are used to indicate convertion problems.
621 * @retval VWRN_NUMBER_TOO_BIG
622 * @retval VWRN_TRAILING_CHARS
623 * @retval VWRN_TRAILING_SPACES
624 * @retval VINF_SUCCESS
625 * @retval VERR_NO_DIGITS
626 *
627 * @param pszValue Pointer to the string value.
628 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
629 * @param uBase The base of the representation used.
630 * If the function will look for known prefixes before defaulting to 10.
631 * @param pi64 Where to store the converted number. (optional)
632 */
633RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64)
634{
635 const char *psz = pszValue;
636 int iShift;
637 int rc;
638 int64_t i64;
639 unsigned char uch;
640
641 /*
642 * Positive/Negative stuff.
643 */
644 bool fPositive = true;
645 for (;; psz++)
646 {
647 if (*psz == '+')
648 fPositive = true;
649 else if (*psz == '-')
650 fPositive = !fPositive;
651 else
652 break;
653 }
654
655 /*
656 * Check for hex prefix.
657 */
658 if (!uBase)
659 {
660 if ( *psz == '0'
661 && (psz[1] == 'x' || psz[1] == 'X')
662 && g_auchDigits[(unsigned char)psz[2]] < 16)
663 {
664 uBase = 16;
665 psz += 2;
666 }
667 else if ( *psz == '0'
668 && g_auchDigits[(unsigned char)psz[1]] < 8)
669 {
670 uBase = 8;
671 psz++;
672 }
673 else
674 uBase = 10;
675 }
676 else if ( uBase == 16
677 && *psz == '0'
678 && (psz[1] == 'x' || psz[1] == 'X')
679 && g_auchDigits[(unsigned char)psz[2]] < 16)
680 psz += 2;
681
682 /*
683 * Interpret the value.
684 * Note: We only support ascii digits at this time... :-)
685 */
686 iShift = g_auchShift[uBase]; /** @todo test this, it's probably not 100% right yet. */
687 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
688 rc = VINF_SUCCESS;
689 i64 = 0;
690 while ((uch = (unsigned char)*psz) != 0)
691 {
692 unsigned char chDigit = g_auchDigits[uch];
693 int64_t i64Prev;
694
695 if (chDigit >= uBase)
696 break;
697
698 i64Prev = i64;
699 i64 *= uBase;
700 i64 += chDigit;
701 if (i64Prev > i64 || (i64Prev >> iShift))
702 rc = VWRN_NUMBER_TOO_BIG;
703 psz++;
704 }
705
706 if (!fPositive)
707 i64 = -i64;
708
709 if (pi64)
710 *pi64 = i64;
711
712 if (psz == pszValue)
713 rc = VERR_NO_DIGITS;
714
715 if (ppszNext)
716 *ppszNext = (char *)psz;
717
718 /*
719 * Warn about trailing chars/spaces.
720 */
721 if ( rc == VINF_SUCCESS
722 && *psz)
723 {
724 while (*psz == ' ' || *psz == '\t')
725 psz++;
726 rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
727 }
728
729 return rc;
730}
731RT_EXPORT_SYMBOL(RTStrToInt64Ex);
732
733
734/**
735 * Converts a string representation of a number to a 64-bit signed number,
736 * making sure the full string is converted.
737 *
738 * @returns iprt status code.
739 * Warnings are used to indicate convertion problems.
740 * @retval VWRN_NUMBER_TOO_BIG
741 * @retval VINF_SUCCESS
742 * @retval VERR_TRAILING_CHARS
743 * @retval VERR_TRAILING_SPACES
744 * @retval VERR_NO_DIGITS
745 *
746 * @param pszValue Pointer to the string value.
747 * @param uBase The base of the representation used.
748 * If the function will look for known prefixes before defaulting to 10.
749 * @param pi64 Where to store the converted number. (optional)
750 */
751RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64)
752{
753 char *psz;
754 int rc = RTStrToInt64Ex(pszValue, &psz, uBase, pi64);
755 if (RT_SUCCESS(rc) && *psz)
756 {
757 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
758 rc = -rc;
759 else
760 {
761 while (*psz == ' ' || *psz == '\t')
762 psz++;
763 rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
764 }
765 }
766 return rc;
767}
768RT_EXPORT_SYMBOL(RTStrToInt64Full);
769
770
771/**
772 * Converts a string representation of a number to a 64-bit signed number.
773 * The base is guessed.
774 *
775 * @returns 64-bit signed number on success.
776 * @returns 0 on failure.
777 * @param pszValue Pointer to the string value.
778 */
779RTDECL(int64_t) RTStrToInt64(const char *pszValue)
780{
781 int64_t i64;
782 int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
783 if (RT_SUCCESS(rc))
784 return i64;
785 return 0;
786}
787RT_EXPORT_SYMBOL(RTStrToInt64);
788
789
790/**
791 * Converts a string representation of a number to a 32-bit signed number.
792 *
793 * @returns iprt status code.
794 * Warnings are used to indicate convertion problems.
795 * @retval VWRN_NUMBER_TOO_BIG
796 * @retval VWRN_TRAILING_CHARS
797 * @retval VWRN_TRAILING_SPACES
798 * @retval VINF_SUCCESS
799 * @retval VERR_NO_DIGITS
800 *
801 * @param pszValue Pointer to the string value.
802 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
803 * @param uBase The base of the representation used.
804 * If the function will look for known prefixes before defaulting to 10.
805 * @param pi32 Where to store the converted number. (optional)
806 */
807RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32)
808{
809 int64_t i64;
810 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
811 if (RT_SUCCESS(rc))
812 {
813 int32_t i32 = (int32_t)i64;
814 if (i64 != (int64_t)i32)
815 rc = VWRN_NUMBER_TOO_BIG;
816 }
817 if (pi32)
818 *pi32 = (int32_t)i64;
819 return rc;
820}
821RT_EXPORT_SYMBOL(RTStrToInt32Ex);
822
823
824/**
825 * Converts a string representation of a number to a 32-bit signed number,
826 * making sure the full string is converted.
827 *
828 * @returns iprt status code.
829 * Warnings are used to indicate convertion problems.
830 * @retval VWRN_NUMBER_TOO_BIG
831 * @retval VINF_SUCCESS
832 * @retval VERR_TRAILING_CHARS
833 * @retval VERR_TRAILING_SPACES
834 * @retval VERR_NO_DIGITS
835 *
836 * @param pszValue Pointer to the string value.
837 * @param uBase The base of the representation used.
838 * If the function will look for known prefixes before defaulting to 10.
839 * @param pi32 Where to store the converted number. (optional)
840 */
841RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32)
842{
843 int64_t i64;
844 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
845 if (RT_SUCCESS(rc))
846 {
847 int32_t i32 = (int32_t)i64;
848 if (i64 != (int64_t)i32)
849 rc = VWRN_NUMBER_TOO_BIG;
850 }
851 if (pi32)
852 *pi32 = (int32_t)i64;
853 return rc;
854}
855RT_EXPORT_SYMBOL(RTStrToInt32Full);
856
857
858/**
859 * Converts a string representation of a number to a 32-bit signed number.
860 * The base is guessed.
861 *
862 * @returns 32-bit signed number on success.
863 * @returns 0 on failure.
864 * @param pszValue Pointer to the string value.
865 */
866RTDECL(int32_t) RTStrToInt32(const char *pszValue)
867{
868 int32_t i32;
869 int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
870 if (RT_SUCCESS(rc))
871 return i32;
872 return 0;
873}
874RT_EXPORT_SYMBOL(RTStrToInt32);
875
876
877/**
878 * Converts a string representation of a number to a 16-bit signed number.
879 *
880 * @returns iprt status code.
881 * Warnings are used to indicate convertion problems.
882 * @retval VWRN_NUMBER_TOO_BIG
883 * @retval VWRN_TRAILING_CHARS
884 * @retval VWRN_TRAILING_SPACES
885 * @retval VINF_SUCCESS
886 * @retval VERR_NO_DIGITS
887 *
888 * @param pszValue Pointer to the string value.
889 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
890 * @param uBase The base of the representation used.
891 * If the function will look for known prefixes before defaulting to 10.
892 * @param pi16 Where to store the converted number. (optional)
893 */
894RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16)
895{
896 int64_t i64;
897 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
898 if (RT_SUCCESS(rc))
899 {
900 int16_t i16 = (int16_t)i64;
901 if (i64 != (int64_t)i16)
902 rc = VWRN_NUMBER_TOO_BIG;
903 }
904 if (pi16)
905 *pi16 = (int16_t)i64;
906 return rc;
907}
908RT_EXPORT_SYMBOL(RTStrToInt16Ex);
909
910
911/**
912 * Converts a string representation of a number to a 16-bit signed number,
913 * making sure the full string is converted.
914 *
915 * @returns iprt status code.
916 * Warnings are used to indicate convertion problems.
917 * @retval VWRN_NUMBER_TOO_BIG
918 * @retval VINF_SUCCESS
919 * @retval VERR_TRAILING_CHARS
920 * @retval VERR_TRAILING_SPACES
921 * @retval VERR_NO_DIGITS
922 *
923 * @param pszValue Pointer to the string value.
924 * @param uBase The base of the representation used.
925 * If the function will look for known prefixes before defaulting to 10.
926 * @param pi16 Where to store the converted number. (optional)
927 */
928RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16)
929{
930 int64_t i64;
931 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
932 if (RT_SUCCESS(rc))
933 {
934 int16_t i16 = (int16_t)i64;
935 if (i64 != (int64_t)i16)
936 rc = VWRN_NUMBER_TOO_BIG;
937 }
938 if (pi16)
939 *pi16 = (int16_t)i64;
940 return rc;
941}
942RT_EXPORT_SYMBOL(RTStrToInt16Full);
943
944
945/**
946 * Converts a string representation of a number to a 16-bit signed number.
947 * The base is guessed.
948 *
949 * @returns 16-bit signed number on success.
950 * @returns 0 on failure.
951 * @param pszValue Pointer to the string value.
952 */
953RTDECL(int16_t) RTStrToInt16(const char *pszValue)
954{
955 int16_t i16;
956 int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
957 if (RT_SUCCESS(rc))
958 return i16;
959 return 0;
960}
961RT_EXPORT_SYMBOL(RTStrToInt16);
962
963
964/**
965 * Converts a string representation of a number to a 8-bit signed number.
966 *
967 * @returns iprt status code.
968 * Warnings are used to indicate convertion problems.
969 * @retval VWRN_NUMBER_TOO_BIG
970 * @retval VWRN_TRAILING_CHARS
971 * @retval VWRN_TRAILING_SPACES
972 * @retval VINF_SUCCESS
973 * @retval VERR_NO_DIGITS
974 *
975 * @param pszValue Pointer to the string value.
976 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
977 * @param uBase The base of the representation used.
978 * If the function will look for known prefixes before defaulting to 10.
979 * @param pi8 Where to store the converted number. (optional)
980 */
981RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8)
982{
983 int64_t i64;
984 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
985 if (RT_SUCCESS(rc))
986 {
987 int8_t i8 = (int8_t)i64;
988 if (i64 != (int64_t)i8)
989 rc = VWRN_NUMBER_TOO_BIG;
990 }
991 if (pi8)
992 *pi8 = (int8_t)i64;
993 return rc;
994}
995RT_EXPORT_SYMBOL(RTStrToInt8Ex);
996
997
998/**
999 * Converts a string representation of a number to a 8-bit signed number,
1000 * making sure the full string is converted.
1001 *
1002 * @returns iprt status code.
1003 * Warnings are used to indicate convertion problems.
1004 * @retval VWRN_NUMBER_TOO_BIG
1005 * @retval VINF_SUCCESS
1006 * @retval VERR_TRAILING_CHARS
1007 * @retval VERR_TRAILING_SPACES
1008 * @retval VERR_NO_DIGITS
1009 *
1010 * @param pszValue Pointer to the string value.
1011 * @param uBase The base of the representation used.
1012 * If the function will look for known prefixes before defaulting to 10.
1013 * @param pi8 Where to store the converted number. (optional)
1014 */
1015RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8)
1016{
1017 int64_t i64;
1018 int rc = RTStrToInt64Full(pszValue, uBase, &i64);
1019 if (RT_SUCCESS(rc))
1020 {
1021 int8_t i8 = (int8_t)i64;
1022 if (i64 != (int64_t)i8)
1023 rc = VWRN_NUMBER_TOO_BIG;
1024 }
1025 if (pi8)
1026 *pi8 = (int8_t)i64;
1027 return rc;
1028}
1029RT_EXPORT_SYMBOL(RTStrToInt8Full);
1030
1031
1032/**
1033 * Converts a string representation of a number to a 8-bit signed number.
1034 * The base is guessed.
1035 *
1036 * @returns 8-bit signed number on success.
1037 * @returns 0 on failure.
1038 * @param pszValue Pointer to the string value.
1039 */
1040RTDECL(int8_t) RTStrToInt8(const char *pszValue)
1041{
1042 int8_t i8;
1043 int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
1044 if (RT_SUCCESS(rc))
1045 return i8;
1046 return 0;
1047}
1048RT_EXPORT_SYMBOL(RTStrToInt8);
1049
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