VirtualBox

source: vbox/trunk/src/VBox/Runtime/strtonum.cpp@ 4953

Last change on this file since 4953 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.9 KB
Line 
1/* $Id: strtonum.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - String To Number Convertion.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/string.h>
23#include <iprt/err.h>
24
25
26/*******************************************************************************
27* Global Variables *
28*******************************************************************************/
29/** 8-bit char -> digit. */
30static const unsigned char g_auchDigits[256] =
31{
32 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,
33 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,
34 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,
35 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,
36 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,
37 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,
38 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,
39 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
40};
41/** Approximated overflow shift checks.
42 * @todo make the overflow stuff work for real. */
43static const char g_auchShift[36] =
44{
45 /* 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 */
46 64, 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 50, 50, 51, 51
47};
48
49/*
50#include <stdio.h>
51int main()
52{
53 int i;
54 printf("static const unsigned char g_auchDigits[256] =\n"
55 "{");
56 for (i = 0; i < 256; i++)
57 {
58 int ch = 255;
59 if (i >= '0' && i <= '9')
60 ch = i - '0';
61 else if (i >= 'a' && i <= 'z')
62 ch = i - 'a' + 10;
63 else if (i >= 'A' && i <= 'Z')
64 ch = i - 'A' + 10;
65 if (i == 0)
66 printf("\n %3d", ch);
67 else if ((i % 32) == 0)
68 printf(",\n %3d", ch);
69 else
70 printf(",%3d", ch);
71 }
72 printf("\n"
73 "};\n");
74 return 0;
75}
76*/
77
78
79
80/**
81 * Converts a string representation of a number to a 64-bit unsigned number.
82 *
83 * @returns iprt status code.
84 * Warnings are used to indicate convertion problems.
85 * @param pszValue Pointer to the string value.
86 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
87 * @param uBase The base of the representation used.
88 * If the function will look for known prefixes before defaulting to 10.
89 * @param pu64 Where to store the converted number. (optional)
90 */
91RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64)
92{
93 const char *psz = pszValue;
94
95 /*
96 * Positive/Negative stuff.
97 */
98 bool fPositive = true;
99 for (;; psz++)
100 {
101 if (*psz == '+')
102 fPositive = true;
103 else if (*psz == '-')
104 fPositive = !fPositive;
105 else
106 break;
107 }
108
109 /*
110 * Check for hex prefix.
111 */
112 if (!uBase)
113 {
114 if ( psz[0] == '0'
115 && (psz[1] == 'x' || psz[1] == 'X')
116 && g_auchDigits[(unsigned char)psz[2]] < 16)
117 {
118 uBase = 16;
119 psz += 2;
120 }
121 else if ( psz[0] == '0'
122 && g_auchDigits[(unsigned char)psz[1]] < 8)
123 {
124 uBase = 8;
125 psz++;
126 }
127 else
128 uBase = 10;
129 }
130 else if ( uBase == 16
131 && psz[0] == '0'
132 && (psz[1] == 'x' || psz[1] == 'X')
133 && g_auchDigits[(unsigned char)psz[2]] < 16)
134 psz += 2;
135
136 /*
137 * Interpret the value.
138 * Note: We only support ascii digits at this time... :-)
139 */
140 int iShift = g_auchShift[uBase];
141 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
142 int rc = VINF_SUCCESS;
143 uint64_t u64 = 0;
144 unsigned char uch;
145 while ((uch = (unsigned char)*psz) != 0)
146 {
147 unsigned char chDigit = g_auchDigits[uch];
148 if (chDigit >= uBase)
149 break;
150
151 uint64_t u64Prev = u64;
152 u64 *= uBase;
153 u64 += chDigit;
154 if (u64Prev > u64 || (u64Prev >> iShift))
155 rc = VWRN_NUMBER_TOO_BIG;
156 psz++;
157 }
158
159 if (!fPositive)
160 {
161 if (rc == VINF_SUCCESS)
162 rc = VWRN_NEGATIVE_UNSIGNED;
163 u64 = -(int64_t)u64;
164 }
165
166 if (pu64)
167 *pu64 = u64;
168
169 if (psz == pszValue)
170 rc = VERR_NO_DIGITS;
171
172 if (ppszNext)
173 *ppszNext = (char *)psz;
174
175 return rc;
176}
177
178
179/**
180 * Converts a string representation of a number to a 64-bit unsigned number.
181 * The base is guessed.
182 *
183 * @returns 64-bit unsigned number on success.
184 * @returns 0 on failure.
185 * @param pszValue Pointer to the string value.
186 */
187RTDECL(uint64_t) RTStrToUInt64(const char *pszValue)
188{
189 uint64_t u64;
190 int rc = RTStrToUInt64Ex(pszValue, NULL, 0, &u64);
191 if (RT_SUCCESS(rc))
192 return u64;
193 return 0;
194}
195
196
197/**
198 * Converts a string representation of a number to a 32-bit unsigned number.
199 *
200 * @returns iprt status code.
201 * Warnings are used to indicate convertion problems.
202 * @param pszValue Pointer to the string value.
203 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
204 * @param uBase The base of the representation used.
205 * If the function will look for known prefixes before defaulting to 10.
206 * @param pu32 Where to store the converted number. (optional)
207 */
208RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
209{
210 uint64_t u64;
211 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
212 if (rc == VINF_SUCCESS)
213 {
214 if (u64 & ~0xffffffffULL)
215 rc = VWRN_NUMBER_TOO_BIG;
216 }
217 if (pu32)
218 *pu32 = (uint32_t)u64;
219 return rc;
220}
221
222
223/**
224 * Converts a string representation of a number to a 64-bit unsigned number.
225 * The base is guessed.
226 *
227 * @returns 32-bit unsigned number on success.
228 * @returns 0 on failure.
229 * @param pszValue Pointer to the string value.
230 */
231RTDECL(uint32_t) RTStrToUInt32(const char *pszValue)
232{
233 uint32_t u32;
234 int rc = RTStrToUInt32Ex(pszValue, NULL, 0, &u32);
235 if (RT_SUCCESS(rc))
236 return u32;
237 return 0;
238}
239
240
241/**
242 * Converts a string representation of a number to a 16-bit unsigned number.
243 *
244 * @returns iprt status code.
245 * Warnings are used to indicate convertion problems.
246 * @param pszValue Pointer to the string value.
247 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
248 * @param uBase The base of the representation used.
249 * If the function will look for known prefixes before defaulting to 10.
250 * @param pu16 Where to store the converted number. (optional)
251 */
252RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16)
253{
254 uint64_t u64;
255 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
256 if (rc == VINF_SUCCESS)
257 {
258 if (u64 & ~0xffffULL)
259 rc = VWRN_NUMBER_TOO_BIG;
260 }
261 if (pu16)
262 *pu16 = (uint16_t)u64;
263 return rc;
264}
265
266
267/**
268 * Converts a string representation of a number to a 16-bit unsigned number.
269 * The base is guessed.
270 *
271 * @returns 16-bit unsigned number on success.
272 * @returns 0 on failure.
273 * @param pszValue Pointer to the string value.
274 */
275RTDECL(uint16_t) RTStrToUInt16(const char *pszValue)
276{
277 uint16_t u16;
278 int rc = RTStrToUInt16Ex(pszValue, NULL, 0, &u16);
279 if (RT_SUCCESS(rc))
280 return u16;
281 return 0;
282}
283
284
285/**
286 * Converts a string representation of a number to a 8-bit unsigned number.
287 *
288 * @returns iprt status code.
289 * Warnings are used to indicate convertion problems.
290 * @param pszValue Pointer to the string value.
291 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
292 * @param uBase The base of the representation used.
293 * If the function will look for known prefixes before defaulting to 10.
294 * @param pu8 Where to store the converted number. (optional)
295 */
296RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8)
297{
298 uint64_t u64;
299 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
300 if (rc == VINF_SUCCESS)
301 {
302 if (u64 & ~0xffULL)
303 rc = VWRN_NUMBER_TOO_BIG;
304 }
305 if (pu8)
306 *pu8 = (uint8_t)u64;
307 return rc;
308}
309
310
311/**
312 * Converts a string representation of a number to a 8-bit unsigned number.
313 * The base is guessed.
314 *
315 * @returns 8-bit unsigned number on success.
316 * @returns 0 on failure.
317 * @param pszValue Pointer to the string value.
318 */
319RTDECL(uint8_t) RTStrToUInt8(const char *pszValue)
320{
321 uint8_t u8;
322 int rc = RTStrToUInt8Ex(pszValue, NULL, 0, &u8);
323 if (RT_SUCCESS(rc))
324 return u8;
325 return 0;
326}
327
328
329
330
331
332
333
334/**
335 * Converts a string representation of a number to a 64-bit signed number.
336 *
337 * @returns iprt status code.
338 * Warnings are used to indicate convertion problems.
339 * @param pszValue Pointer to the string value.
340 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
341 * @param uBase The base of the representation used.
342 * If the function will look for known prefixes before defaulting to 10.
343 * @param pi64 Where to store the converted number. (optional)
344 */
345RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64)
346{
347 const char *psz = pszValue;
348
349 /*
350 * Positive/Negative stuff.
351 */
352 bool fPositive = true;
353 for (;; psz++)
354 {
355 if (*psz == '+')
356 fPositive = true;
357 else if (*psz == '-')
358 fPositive = !fPositive;
359 else
360 break;
361 }
362
363 /*
364 * Check for hex prefix.
365 */
366 if (!uBase)
367 {
368 if ( *psz == '0'
369 && (psz[1] == 'x' || psz[1] == 'X')
370 && g_auchDigits[(unsigned char)psz[2]] < 16)
371 {
372 uBase = 16;
373 psz += 2;
374 }
375 else if ( *psz == '0'
376 && g_auchDigits[(unsigned char)psz[1]] < 8)
377 {
378 uBase = 8;
379 psz++;
380 }
381 else
382 uBase = 10;
383 }
384 else if ( uBase == 16
385 && *psz == '0'
386 && (psz[1] == 'x' || psz[1] == 'X')
387 && g_auchDigits[(unsigned char)psz[2]] < 16)
388 psz += 2;
389
390 /*
391 * Interpret the value.
392 * Note: We only support ascii digits at this time... :-)
393 */
394 //int iShift = g_auchShift[uBase];
395 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
396 int rc = VINF_SUCCESS;
397 int64_t i64 = 0;
398 unsigned char uch;
399 while ((uch = (unsigned char)*psz) != 0)
400 {
401 unsigned char chDigit = g_auchDigits[uch];
402 if (chDigit >= uBase)
403 break;
404
405 int64_t i64Prev = i64;
406 i64 *= uBase;
407 i64 += chDigit;
408 if (i64Prev > i64/* || (i64Prev >> iShift)*/)
409 rc = VWRN_NUMBER_TOO_BIG;
410 psz++;
411 }
412
413 if (!fPositive)
414 i64 = -i64;
415
416 if (pi64)
417 *pi64 = i64;
418
419 if (psz == pszValue)
420 rc = VERR_NO_DIGITS;
421
422 if (ppszNext)
423 *ppszNext = (char *)psz;
424
425 return rc;
426}
427
428
429/**
430 * Converts a string representation of a number to a 64-bit signed number.
431 * The base is guessed.
432 *
433 * @returns 64-bit signed number on success.
434 * @returns 0 on failure.
435 * @param pszValue Pointer to the string value.
436 */
437RTDECL(int64_t) RTStrToInt64(const char *pszValue)
438{
439 int64_t i64;
440 int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
441 if (RT_SUCCESS(rc))
442 return i64;
443 return 0;
444}
445
446
447/**
448 * Converts a string representation of a number to a 32-bit signed number.
449 *
450 * @returns iprt status code.
451 * Warnings are used to indicate convertion problems.
452 * @param pszValue Pointer to the string value.
453 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
454 * @param uBase The base of the representation used.
455 * If the function will look for known prefixes before defaulting to 10.
456 * @param pi32 Where to store the converted number. (optional)
457 */
458RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32)
459{
460 int64_t i64;
461 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
462 if (rc == VINF_SUCCESS)
463 {
464 int32_t i32 = (int32_t)i64;
465 if (i64 != (int64_t)i32)
466 rc = VWRN_NUMBER_TOO_BIG;
467 }
468 if (pi32)
469 *pi32 = (int32_t)i64;
470 return rc;
471}
472
473
474/**
475 * Converts a string representation of a number to a 32-bit signed number.
476 * The base is guessed.
477 *
478 * @returns 32-bit signed number on success.
479 * @returns 0 on failure.
480 * @param pszValue Pointer to the string value.
481 */
482RTDECL(int32_t) RTStrToInt32(const char *pszValue)
483{
484 int32_t i32;
485 int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
486 if (RT_SUCCESS(rc))
487 return i32;
488 return 0;
489}
490
491
492/**
493 * Converts a string representation of a number to a 16-bit signed number.
494 *
495 * @returns iprt status code.
496 * Warnings are used to indicate convertion problems.
497 * @param pszValue Pointer to the string value.
498 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
499 * @param uBase The base of the representation used.
500 * If the function will look for known prefixes before defaulting to 10.
501 * @param pi16 Where to store the converted number. (optional)
502 */
503RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16)
504{
505 int64_t i64;
506 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
507 if (rc == VINF_SUCCESS)
508 {
509 int16_t i16 = (int16_t)i64;
510 if (i64 != (int64_t)i16)
511 rc = VWRN_NUMBER_TOO_BIG;
512 }
513 if (pi16)
514 *pi16 = (int16_t)i64;
515 return rc;
516}
517
518
519/**
520 * Converts a string representation of a number to a 16-bit signed number.
521 * The base is guessed.
522 *
523 * @returns 16-bit signed number on success.
524 * @returns 0 on failure.
525 * @param pszValue Pointer to the string value.
526 */
527RTDECL(int16_t) RTStrToInt16(const char *pszValue)
528{
529 int16_t i16;
530 int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
531 if (RT_SUCCESS(rc))
532 return i16;
533 return 0;
534}
535
536
537/**
538 * Converts a string representation of a number to a 8-bit signed number.
539 *
540 * @returns iprt status code.
541 * Warnings are used to indicate convertion problems.
542 * @param pszValue Pointer to the string value.
543 * @param ppszNext Where to store the pointer to the first char following the number. (Optional)
544 * @param uBase The base of the representation used.
545 * If the function will look for known prefixes before defaulting to 10.
546 * @param pi8 Where to store the converted number. (optional)
547 */
548RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8)
549{
550 int64_t i64;
551 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
552 if (rc == VINF_SUCCESS)
553 {
554 int8_t i8 = (int8_t)i64;
555 if (i64 != (int64_t)i8)
556 rc = VWRN_NUMBER_TOO_BIG;
557 }
558 if (pi8)
559 *pi8 = (int8_t)i64;
560 return rc;
561}
562
563
564/**
565 * Converts a string representation of a number to a 8-bit signed number.
566 * The base is guessed.
567 *
568 * @returns 8-bit signed number on success.
569 * @returns 0 on failure.
570 * @param pszValue Pointer to the string value.
571 */
572RTDECL(int8_t) RTStrToInt8(const char *pszValue)
573{
574 int8_t i8;
575 int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
576 if (RT_SUCCESS(rc))
577 return i8;
578 return 0;
579}
580
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