VirtualBox

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

Last change on this file since 3392 was 2981, checked in by vboxsync, 17 years ago

InnoTek -> innotek: all the headers and comments.

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