VirtualBox

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

Last change on this file since 24659 was 24659, checked in by vboxsync, 16 years ago

build grumble.

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

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