VirtualBox

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

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

RTStrVersionToUInt32: bird review, things todo.

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