Changeset 96127 in vbox
- Timestamp:
- Aug 9, 2022 10:00:57 AM (2 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/string.h
r94421 r96127 2840 2840 * @retval VERR_NO_DIGITS 2841 2841 * 2842 * @param pszValue Pointer to the string value. 2843 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 2844 * @param uBase The base of the representation used. 2845 * If 0 the function will look for known prefixes before defaulting to 10. 2846 * @param pu64 Where to store the converted number. (optional) 2847 */ 2848 RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64); 2842 * @param pszValue Pointer to the string value. 2843 * @param ppszNext Where to store the pointer to the first char 2844 * following the number. (Optional) 2845 * @param uBaseAndMaxLen The low byte is the base of the representation, the 2846 * upper 24 bits are the max length to parse. If the base 2847 * is zero the function will look for known prefixes before 2848 * defaulting to 10. A max length of zero means no length 2849 * restriction. 2850 * @param pu64 Where to store the converted number. (optional) 2851 */ 2852 RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndLen, uint64_t *pu64); 2849 2853 2850 2854 /** … … 2861 2865 * @retval VERR_TRAILING_CHARS 2862 2866 * 2863 * @param pszValue Pointer to the string value. 2864 * @param uBase The base of the representation used. 2865 * If 0 the function will look for known prefixes before defaulting to 10. 2866 * @param pu64 Where to store the converted number. (optional) 2867 * @param pszValue Pointer to the string value. 2868 * @param uBaseAndMaxLen The low byte is the base of the representation, the 2869 * upper 24 bits are the max length to parse. If the base 2870 * is zero the function will look for known prefixes before 2871 * defaulting to 10. A max length of zero means no length 2872 * restriction. 2873 * @param pu64 Where to store the converted number. (optional) 2867 2874 */ 2868 2875 RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64); … … 2890 2897 * @retval VERR_NO_DIGITS 2891 2898 * 2892 * @param pszValue Pointer to the string value. 2893 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 2894 * @param uBase The base of the representation used. 2895 * If 0 the function will look for known prefixes before defaulting to 10. 2896 * @param pu32 Where to store the converted number. (optional) 2899 * @param pszValue Pointer to the string value. 2900 * @param ppszNext Where to store the pointer to the first char 2901 * following the number. (Optional) 2902 * @param uBaseAndMaxLen The low byte is the base of the representation, the 2903 * upper 24 bits are the max length to parse. If the base 2904 * is zero the function will look for known prefixes before 2905 * defaulting to 10. A max length of zero means no length 2906 * restriction. 2907 * @param pu32 Where to store the converted number. (optional) 2897 2908 */ 2898 2909 RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32); … … 2911 2922 * @retval VERR_TRAILING_CHARS 2912 2923 * 2913 * @param pszValue Pointer to the string value. 2914 * @param uBase The base of the representation used. 2915 * If 0 the function will look for known prefixes before defaulting to 10. 2916 * @param pu32 Where to store the converted number. (optional) 2924 * @param pszValue Pointer to the string value. 2925 * @param uBaseAndMaxLen The low byte is the base of the representation, the 2926 * upper 24 bits are the max length to parse. If the base 2927 * is zero the function will look for known prefixes before 2928 * defaulting to 10. A max length of zero means no length 2929 * restriction. 2930 * @param pu32 Where to store the converted number. (optional) 2917 2931 */ 2918 2932 RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32); … … 2940 2954 * @retval VERR_NO_DIGITS 2941 2955 * 2942 * @param pszValue Pointer to the string value. 2943 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 2944 * @param uBase The base of the representation used. 2945 * If 0 the function will look for known prefixes before defaulting to 10. 2946 * @param pu16 Where to store the converted number. (optional) 2956 * @param pszValue Pointer to the string value. 2957 * @param ppszNext Where to store the pointer to the first char 2958 * following the number. (Optional) 2959 * @param uBaseAndMaxLen The low byte is the base of the representation, the 2960 * upper 24 bits are the max length to parse. If the base 2961 * is zero the function will look for known prefixes before 2962 * defaulting to 10. A max length of zero means no length 2963 * restriction. 2964 * @param pu16 Where to store the converted number. (optional) 2947 2965 */ 2948 2966 RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16); … … 2990 3008 * @retval VERR_NO_DIGITS 2991 3009 * 2992 * @param pszValue Pointer to the string value. 2993 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 2994 * @param uBase The base of the representation used. 2995 * If 0 the function will look for known prefixes before defaulting to 10. 2996 * @param pu8 Where to store the converted number. (optional) 3010 * @param pszValue Pointer to the string value. 3011 * @param ppszNext Where to store the pointer to the first char 3012 * following the number. (Optional) 3013 * @param uBaseAndMaxLen The low byte is the base of the representation, the 3014 * upper 24 bits are the max length to parse. If the base 3015 * is zero the function will look for known prefixes before 3016 * defaulting to 10. A max length of zero means no length 3017 * restriction. 3018 * @param pu8 Where to store the converted number. (optional) 2997 3019 */ 2998 3020 RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8); … … 3011 3033 * @retval VERR_TRAILING_CHARS 3012 3034 * 3013 * @param pszValue Pointer to the string value. 3014 * @param uBase The base of the representation used. 3015 * If 0 the function will look for known prefixes before defaulting to 10. 3016 * @param pu8 Where to store the converted number. (optional) 3035 * @param pszValue Pointer to the string value. 3036 * @param uBaseAndMaxLen The low byte is the base of the representation, the 3037 * upper 24 bits are the max length to parse. If the base 3038 * is zero the function will look for known prefixes before 3039 * defaulting to 10. A max length of zero means no length 3040 * restriction. 3041 * @param pu8 Where to store the converted number. (optional) 3017 3042 */ 3018 3043 RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8); -
trunk/src/VBox/Runtime/common/string/strtonum.cpp
r93115 r96127 110 110 * @retval VERR_NO_DIGITS 111 111 * 112 * @param pszValue Pointer to the string value. 113 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 114 * @param uBase The base of the representation used. 115 * If the function will look for known prefixes before defaulting to 10. 116 * @param pu64 Where to store the converted number. (optional) 117 */ 118 RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64) 112 * @param pszValue Pointer to the string value. 113 * @param ppszNext Where to store the pointer to the first char 114 * following the number. (Optional) 115 * @param uBaseAndMaxLen The low byte is the base of the representation, the 116 * upper 24 bits are the max length to parse. If the base 117 * is zero the function will look for known prefixes before 118 * defaulting to 10. A max length of zero means no length 119 * restriction. 120 * @param pu64 Where to store the converted number. (optional) 121 */ 122 RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint64_t *pu64) 119 123 { 120 124 const char *psz = pszValue; … … 123 127 uint64_t u64; 124 128 unsigned char uch; 129 bool fPositive; 130 131 /* 132 * Split the base and length limit (latter is chiefly for sscanf). 133 */ 134 unsigned uBase = uBaseAndMaxLen & 0xff; 135 unsigned cchMax = uBaseAndMaxLen >> 8; 136 if (cchMax == 0) 137 cchMax = ~0U; 138 AssertStmt(uBase < RT_ELEMENTS(g_auchShift), uBase = 0); 125 139 126 140 /* 127 141 * Positive/Negative stuff. 128 142 */ 129 boolfPositive = true;130 for (;; psz++)143 fPositive = true; 144 while (cchMax > 0) 131 145 { 132 146 if (*psz == '+') … … 136 150 else 137 151 break; 152 psz++; 153 cchMax--; 138 154 } 139 155 … … 143 159 if (!uBase) 144 160 { 145 if ( psz[0] == '0' 146 && (psz[1] == 'x' || psz[1] == 'X') 147 && g_auchDigits[(unsigned char)psz[2]] < 16) 161 uBase = 10; 162 if (psz[0] == '0') 148 163 { 149 uBase = 16; 150 psz += 2; 164 if ( psz[0] == '0' 165 && cchMax > 1 166 && (psz[1] == 'x' || psz[1] == 'X') 167 && g_auchDigits[(unsigned char)psz[2]] < 16) 168 { 169 uBase = 16; 170 psz += 2; 171 cchMax -= 2; 172 } 173 else if ( psz[0] == '0' 174 && g_auchDigits[(unsigned char)psz[1]] < 8) 175 uBase = 8; /* don't skip the zero, in case it's alone. */ 151 176 } 152 else if ( psz[0] == '0'153 && g_auchDigits[(unsigned char)psz[1]] < 8)154 {155 uBase = 8;156 psz++;157 }158 else159 uBase = 10;160 177 } 161 178 else if ( uBase == 16 162 179 && psz[0] == '0' 180 && cchMax > 1 163 181 && (psz[1] == 'x' || psz[1] == 'X') 164 182 && g_auchDigits[(unsigned char)psz[2]] < 16) 165 psz += 2; 183 { 184 cchMax -= 2; 185 psz += 2; 186 } 166 187 167 188 /* … … 169 190 * Note: We only support ascii digits at this time... :-) 170 191 */ 171 iShift = g_auchShift[uBase];172 192 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */ 173 rc = VINF_SUCCESS; 174 u64 = 0; 175 while ((uch = (unsigned char)*psz) != 0) 193 iShift = g_auchShift[uBase]; 194 rc = VINF_SUCCESS; 195 u64 = 0; 196 while (cchMax > 0 && (uch = (unsigned char)*psz) != 0) 176 197 { 177 198 unsigned char chDigit = g_auchDigits[uch]; … … 182 203 183 204 u64Prev = u64; 184 u64 *= uBase;185 u64 += chDigit;205 u64 *= uBase; 206 u64 += chDigit; 186 207 if (u64Prev > u64 || (u64Prev >> iShift)) 187 208 rc = VWRN_NUMBER_TOO_BIG; 188 209 psz++; 210 cchMax--; 189 211 } 190 212 … … 208 230 * Warn about trailing chars/spaces. 209 231 */ 210 if ( rc == VINF_SUCCESS 211 && *psz) 212 { 213 while (*psz == ' ' || *psz == '\t') 214 psz++; 215 rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 232 if ( rc == VINF_SUCCESS 233 && *psz 234 && cchMax > 0) 235 { 236 while (cchMax > 0 && (*psz == ' ' || *psz == '\t')) 237 psz++, cchMax--; 238 rc = cchMax > 0 && *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 216 239 } 217 240 … … 234 257 * @retval VERR_TRAILING_CHARS 235 258 * 236 * @param pszValue Pointer to the string value. 237 * @param uBase The base of the representation used. 238 * If the function will look for known prefixes before defaulting to 10. 239 * @param pu64 Where to store the converted number. (optional) 240 */ 241 RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64) 259 * @param pszValue Pointer to the string value. 260 * @param uBaseAndMaxLen The low byte is the base of the representation, the 261 * upper 24 bits are the max length to parse. If the base 262 * is zero the function will look for known prefixes before 263 * defaulting to 10. A max length of zero means no length 264 * restriction. 265 * @param pu64 Where to store the converted number. (optional) 266 */ 267 RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, uint64_t *pu64) 242 268 { 243 269 char *psz; 244 int rc = RTStrToUInt64Ex(pszValue, &psz, uBase , pu64);270 int rc = RTStrToUInt64Ex(pszValue, &psz, uBaseAndMaxLen, pu64); 245 271 if (RT_SUCCESS(rc) && *psz) 246 272 { 247 273 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES) 248 274 rc = -rc; 249 else 275 else if (rc != VINF_SUCCESS) 250 276 { 251 while (*psz == ' ' || *psz == '\t') 252 psz++; 253 rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES; 277 unsigned cchMax = uBaseAndMaxLen >> 8; 278 if (!cchMax) 279 cchMax = ~0U; 280 else 281 cchMax -= (unsigned)(psz - pszValue); 282 if (cchMax > 0) 283 { 284 while (cchMax > 0 && (*psz == ' ' || *psz == '\t')) 285 psz++, cchMax--; 286 rc = cchMax > 0 && *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES; 287 } 254 288 } 255 289 } … … 290 324 * @retval VERR_NO_DIGITS 291 325 * 292 * @param pszValue Pointer to the string value. 293 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 294 * @param uBase The base of the representation used. 295 * If the function will look for known prefixes before defaulting to 10. 296 * @param pu32 Where to store the converted number. (optional) 297 */ 298 RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32) 326 * @param pszValue Pointer to the string value. 327 * @param ppszNext Where to store the pointer to the first char 328 * following the number. (Optional) 329 * @param uBaseAndMaxLen The low byte is the base of the representation, the 330 * upper 24 bits are the max length to parse. If the base 331 * is zero the function will look for known prefixes before 332 * defaulting to 10. A max length of zero means no length 333 * restriction. 334 * @param pu32 Where to store the converted number. (optional) 335 */ 336 RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint32_t *pu32) 299 337 { 300 338 uint64_t u64; 301 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase , &u64);339 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64); 302 340 if (RT_SUCCESS(rc)) 303 341 { … … 325 363 * @retval VERR_TRAILING_CHARS 326 364 * 327 * @param pszValue Pointer to the string value. 328 * @param uBase The base of the representation used. 329 * If the function will look for known prefixes before defaulting to 10. 330 * @param pu32 Where to store the converted number. (optional) 331 */ 332 RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32) 365 * @param pszValue Pointer to the string value. 366 * @param uBaseAndMaxLen The low byte is the base of the representation, the 367 * upper 24 bits are the max length to parse. If the base 368 * is zero the function will look for known prefixes before 369 * defaulting to 10. A max length of zero means no length 370 * restriction. 371 * @param pu32 Where to store the converted number. (optional) 372 */ 373 RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, uint32_t *pu32) 333 374 { 334 375 uint64_t u64; 335 int rc = RTStrToUInt64Full(pszValue, uBase , &u64);376 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64); 336 377 if (RT_SUCCESS(rc)) 337 378 { … … 377 418 * @retval VERR_NO_DIGITS 378 419 * 379 * @param pszValue Pointer to the string value. 380 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 381 * @param uBase The base of the representation used. 382 * If the function will look for known prefixes before defaulting to 10. 383 * @param pu16 Where to store the converted number. (optional) 384 */ 385 RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16) 420 * @param pszValue Pointer to the string value. 421 * @param ppszNext Where to store the pointer to the first char 422 * following the number. (Optional) 423 * @param uBaseAndMaxLen The low byte is the base of the representation, the 424 * upper 24 bits are the max length to parse. If the base 425 * is zero the function will look for known prefixes before 426 * defaulting to 10. A max length of zero means no length 427 * restriction. 428 * @param pu16 Where to store the converted number. (optional) 429 */ 430 RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint16_t *pu16) 386 431 { 387 432 uint64_t u64; 388 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase , &u64);433 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64); 389 434 if (RT_SUCCESS(rc)) 390 435 { … … 412 457 * @retval VERR_TRAILING_CHARS 413 458 * 414 * @param pszValue Pointer to the string value. 415 * @param uBase The base of the representation used. 416 * If the function will look for known prefixes before defaulting to 10. 417 * @param pu16 Where to store the converted number. (optional) 418 */ 419 RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16) 459 * @param pszValue Pointer to the string value. 460 * @param uBaseAndMaxLen The low byte is the base of the representation, the 461 * upper 24 bits are the max length to parse. If the base 462 * is zero the function will look for known prefixes before 463 * defaulting to 10. A max length of zero means no length 464 * restriction. 465 * @param pu16 Where to store the converted number. (optional) 466 */ 467 RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, uint16_t *pu16) 420 468 { 421 469 uint64_t u64; 422 int rc = RTStrToUInt64Full(pszValue, uBase , &u64);470 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64); 423 471 if (RT_SUCCESS(rc)) 424 472 { … … 464 512 * @retval VERR_NO_DIGITS 465 513 * 466 * @param pszValue Pointer to the string value. 467 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 468 * @param uBase The base of the representation used. 469 * If the function will look for known prefixes before defaulting to 10. 470 * @param pu8 Where to store the converted number. (optional) 471 */ 472 RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8) 514 * @param pszValue Pointer to the string value. 515 * @param ppszNext Where to store the pointer to the first char 516 * following the number. (Optional) 517 * @param uBaseAndMaxLen The low byte is the base of the representation, the 518 * upper 24 bits are the max length to parse. If the base 519 * is zero the function will look for known prefixes before 520 * defaulting to 10. A max length of zero means no length 521 * restriction. 522 * @param pu8 Where to store the converted number. (optional) 523 */ 524 RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, uint8_t *pu8) 473 525 { 474 526 uint64_t u64; 475 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase , &u64);527 int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &u64); 476 528 if (RT_SUCCESS(rc)) 477 529 { … … 499 551 * @retval VERR_TRAILING_CHARS 500 552 * 501 * @param pszValue Pointer to the string value. 502 * @param uBase The base of the representation used. 503 * If the function will look for known prefixes before defaulting to 10. 504 * @param pu8 Where to store the converted number. (optional) 505 */ 506 RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8) 553 * @param pszValue Pointer to the string value. 554 * @param uBaseAndMaxLen The low byte is the base of the representation, the 555 * upper 24 bits are the max length to parse. If the base 556 * is zero the function will look for known prefixes before 557 * defaulting to 10. A max length of zero means no length 558 * restriction. 559 * @param pu8 Where to store the converted number. (optional) 560 */ 561 RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, uint8_t *pu8) 507 562 { 508 563 uint64_t u64; 509 int rc = RTStrToUInt64Full(pszValue, uBase , &u64);564 int rc = RTStrToUInt64Full(pszValue, uBaseAndMaxLen, &u64); 510 565 if (RT_SUCCESS(rc)) 511 566 { … … 555 610 * @retval VERR_NO_DIGITS 556 611 * 557 * @param pszValue Pointer to the string value. 558 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 559 * @param uBase The base of the representation used. 560 * If the function will look for known prefixes before defaulting to 10. 561 * @param pi64 Where to store the converted number. (optional) 562 */ 563 RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64) 612 * @param pszValue Pointer to the string value. 613 * @param ppszNext Where to store the pointer to the first char 614 * following the number. (Optional) 615 * @param uBaseAndMaxLen The low byte is the base of the representation, the 616 * upper 24 bits are the max length to parse. If the base 617 * is zero the function will look for known prefixes before 618 * defaulting to 10. A max length of zero means no length 619 * restriction. 620 * @param pi64 Where to store the converted number. (optional) 621 */ 622 RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int64_t *pi64) 564 623 { 565 624 const char *psz = pszValue; … … 568 627 uint64_t u64; 569 628 unsigned char uch; 629 bool fPositive; 630 631 /* 632 * Split the base and length limit (latter is chiefly for sscanf). 633 */ 634 unsigned uBase = uBaseAndMaxLen & 0xff; 635 unsigned cchMax = uBaseAndMaxLen >> 8; 636 if (cchMax == 0) 637 cchMax = ~0U; 638 AssertStmt(uBase < RT_ELEMENTS(g_auchShift), uBase = 0); 570 639 571 640 /* 572 641 * Positive/Negative stuff. 573 642 */ 574 boolfPositive = true;575 for (;; psz++)643 fPositive = true; 644 while (cchMax > 0) 576 645 { 577 646 if (*psz == '+') … … 581 650 else 582 651 break; 652 psz++; 653 cchMax--; 583 654 } 584 655 … … 588 659 if (!uBase) 589 660 { 590 if ( *psz == '0' 591 && (psz[1] == 'x' || psz[1] == 'X') 592 && g_auchDigits[(unsigned char)psz[2]] < 16) 661 uBase = 10; 662 if (psz[0] == '0') 593 663 { 594 uBase = 16; 595 psz += 2; 664 if ( psz[0] == '0' 665 && cchMax > 1 666 && (psz[1] == 'x' || psz[1] == 'X') 667 && g_auchDigits[(unsigned char)psz[2]] < 16) 668 { 669 uBase = 16; 670 psz += 2; 671 cchMax -= 2; 672 } 673 else if ( psz[0] == '0' 674 && g_auchDigits[(unsigned char)psz[1]] < 8) 675 uBase = 8; /* don't skip the zero, in case it's alone. */ 596 676 } 597 else if ( *psz == '0'598 && g_auchDigits[(unsigned char)psz[1]] < 8)599 {600 uBase = 8;601 psz++;602 }603 else604 uBase = 10;605 677 } 606 678 else if ( uBase == 16 607 && *psz == '0' 679 && psz[0] == '0' 680 && cchMax > 1 608 681 && (psz[1] == 'x' || psz[1] == 'X') 609 682 && g_auchDigits[(unsigned char)psz[2]] < 16) 610 psz += 2; 683 { 684 cchMax -= 2; 685 psz += 2; 686 } 611 687 612 688 /* … … 614 690 * Note: We only support ascii digits at this time... :-) 615 691 */ 616 iShift = g_auchShift[uBase];617 692 pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */ 618 rc = VINF_SUCCESS; 619 u64 = 0; 620 while ((uch = (unsigned char)*psz) != 0) 693 iShift = g_auchShift[uBase]; 694 rc = VINF_SUCCESS; 695 u64 = 0; 696 while (cchMax > 0 && (uch = (unsigned char)*psz) != 0) 621 697 { 622 698 unsigned char chDigit = g_auchDigits[uch]; … … 627 703 628 704 u64Prev = u64; 629 u64 *= uBase;630 u64 += chDigit;705 u64 *= uBase; 706 u64 += chDigit; 631 707 if (u64Prev > u64 || (u64Prev >> iShift)) 632 708 rc = VWRN_NUMBER_TOO_BIG; 633 709 psz++; 710 cchMax--; 634 711 } 635 712 … … 661 738 * Warn about trailing chars/spaces. 662 739 */ 663 if ( rc == VINF_SUCCESS 664 && *psz) 665 { 666 while (*psz == ' ' || *psz == '\t') 667 psz++; 668 rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 740 if ( rc == VINF_SUCCESS 741 && cchMax > 0 742 && *psz) 743 { 744 while (cchMax > 0 && (*psz == ' ' || *psz == '\t')) 745 psz++, cchMax--; 746 rc = cchMax > 0 && *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 669 747 } 670 748 … … 686 764 * @retval VERR_NO_DIGITS 687 765 * 688 * @param pszValue Pointer to the string value. 689 * @param uBase The base of the representation used. 690 * If the function will look for known prefixes before defaulting to 10. 691 * @param pi64 Where to store the converted number. (optional) 692 */ 693 RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64) 766 * @param pszValue Pointer to the string value. 767 * @param uBaseAndMaxLen The low byte is the base of the representation, the 768 * upper 24 bits are the max length to parse. If the base 769 * is zero the function will look for known prefixes before 770 * defaulting to 10. A max length of zero means no length 771 * restriction. 772 * @param pi64 Where to store the converted number. (optional) 773 */ 774 RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, int64_t *pi64) 694 775 { 695 776 char *psz; 696 int rc = RTStrToInt64Ex(pszValue, &psz, uBase , pi64);777 int rc = RTStrToInt64Ex(pszValue, &psz, uBaseAndMaxLen, pi64); 697 778 if (RT_SUCCESS(rc) && *psz) 698 779 { 699 780 if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES) 700 781 rc = -rc; 701 else 782 else if (rc != VINF_SUCCESS) 702 783 { 703 while (*psz == ' ' || *psz == '\t') 704 psz++; 705 rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES; 784 unsigned cchMax = uBaseAndMaxLen >> 8; 785 if (!cchMax) 786 cchMax = ~0U; 787 else 788 cchMax -= (unsigned)(psz - pszValue); 789 if (cchMax > 0) 790 { 791 while (cchMax > 0 && (*psz == ' ' || *psz == '\t')) 792 psz++, cchMax--; 793 rc = cchMax > 0 && *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES; 794 } 706 795 } 707 796 } … … 741 830 * @retval VERR_NO_DIGITS 742 831 * 743 * @param pszValue Pointer to the string value. 744 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 745 * @param uBase The base of the representation used. 746 * If the function will look for known prefixes before defaulting to 10. 747 * @param pi32 Where to store the converted number. (optional) 748 */ 749 RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32) 832 * @param pszValue Pointer to the string value. 833 * @param ppszNext Where to store the pointer to the first char 834 * following the number. (Optional) 835 * @param uBaseAndMaxLen The low byte is the base of the representation, the 836 * upper 24 bits are the max length to parse. If the base 837 * is zero the function will look for known prefixes before 838 * defaulting to 10. A max length of zero means no length 839 * restriction. 840 * @param pi32 Where to store the converted number. (optional) 841 */ 842 RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int32_t *pi32) 750 843 { 751 844 int64_t i64; 752 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase , &i64);845 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64); 753 846 if (RT_SUCCESS(rc)) 754 847 { … … 776 869 * @retval VERR_NO_DIGITS 777 870 * 778 * @param pszValue Pointer to the string value. 779 * @param uBase The base of the representation used. 780 * If the function will look for known prefixes before defaulting to 10. 781 * @param pi32 Where to store the converted number. (optional) 782 */ 783 RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32) 871 * @param pszValue Pointer to the string value. 872 * @param uBaseAndMaxLen The low byte is the base of the representation, the 873 * upper 24 bits are the max length to parse. If the base 874 * is zero the function will look for known prefixes before 875 * defaulting to 10. A max length of zero means no length 876 * restriction. 877 * @param pi32 Where to store the converted number. (optional) 878 */ 879 RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, int32_t *pi32) 784 880 { 785 881 int64_t i64; 786 int rc = RTStrToInt64Full(pszValue, uBase , &i64);882 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64); 787 883 if (RT_SUCCESS(rc)) 788 884 { … … 828 924 * @retval VERR_NO_DIGITS 829 925 * 830 * @param pszValue Pointer to the string value. 831 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 832 * @param uBase The base of the representation used. 833 * If the function will look for known prefixes before defaulting to 10. 834 * @param pi16 Where to store the converted number. (optional) 835 */ 836 RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16) 926 * @param pszValue Pointer to the string value. 927 * @param ppszNext Where to store the pointer to the first char 928 * following the number. (Optional) 929 * @param pszValue Pointer to the string value. 930 * @param uBaseAndMaxLen The low byte is the base of the representation, the 931 * upper 24 bits are the max length to parse. If the base 932 * is zero the function will look for known prefixes before 933 * defaulting to 10. A max length of zero means no length 934 * restriction. 935 * @param pu8 Where to store the converted number. (optional) 936 * @param pi16 Where to store the converted number. (optional) 937 */ 938 RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int16_t *pi16) 837 939 { 838 940 int64_t i64; 839 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase , &i64);941 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64); 840 942 if (RT_SUCCESS(rc)) 841 943 { … … 863 965 * @retval VERR_NO_DIGITS 864 966 * 865 * @param pszValue Pointer to the string value. 866 * @param uBase The base of the representation used. 867 * If the function will look for known prefixes before defaulting to 10. 868 * @param pi16 Where to store the converted number. (optional) 869 */ 870 RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16) 967 * @param pszValue Pointer to the string value. 968 * @param uBaseAndMaxLen The low byte is the base of the representation, the 969 * upper 24 bits are the max length to parse. If the base 970 * is zero the function will look for known prefixes before 971 * defaulting to 10. A max length of zero means no length 972 * restriction. 973 * @param pi16 Where to store the converted number. (optional) 974 */ 975 RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, int16_t *pi16) 871 976 { 872 977 int64_t i64; 873 int rc = RTStrToInt64Full(pszValue, uBase , &i64);978 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64); 874 979 if (RT_SUCCESS(rc)) 875 980 { … … 915 1020 * @retval VERR_NO_DIGITS 916 1021 * 917 * @param pszValue Pointer to the string value. 918 * @param ppszNext Where to store the pointer to the first char following the number. (Optional) 919 * @param uBase The base of the representation used. 920 * If the function will look for known prefixes before defaulting to 10. 921 * @param pi8 Where to store the converted number. (optional) 922 */ 923 RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8) 1022 * @param pszValue Pointer to the string value. 1023 * @param ppszNext Where to store the pointer to the first char 1024 * following the number. (Optional) 1025 * @param uBaseAndMaxLen The low byte is the base of the representation, the 1026 * upper 24 bits are the max length to parse. If the base 1027 * is zero the function will look for known prefixes before 1028 * defaulting to 10. A max length of zero means no length 1029 * restriction. 1030 * @param pi8 Where to store the converted number. (optional) 1031 */ 1032 RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, int8_t *pi8) 924 1033 { 925 1034 int64_t i64; 926 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase , &i64);1035 int rc = RTStrToInt64Ex(pszValue, ppszNext, uBaseAndMaxLen, &i64); 927 1036 if (RT_SUCCESS(rc)) 928 1037 { … … 950 1059 * @retval VERR_NO_DIGITS 951 1060 * 952 * @param pszValue Pointer to the string value. 953 * @param uBase The base of the representation used. 954 * If the function will look for known prefixes before defaulting to 10. 955 * @param pi8 Where to store the converted number. (optional) 956 */ 957 RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8) 1061 * @param pszValue Pointer to the string value. 1062 * @param uBaseAndMaxLen The low byte is the base of the representation, the 1063 * upper 24 bits are the max length to parse. If the base 1064 * is zero the function will look for known prefixes before 1065 * defaulting to 10. A max length of zero means no length 1066 * restriction. 1067 * @param pi8 Where to store the converted number. (optional) 1068 */ 1069 RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, int8_t *pi8) 958 1070 { 959 1071 int64_t i64; 960 int rc = RTStrToInt64Full(pszValue, uBase , &i64);1072 int rc = RTStrToInt64Full(pszValue, uBaseAndMaxLen, &i64); 961 1073 if (RT_SUCCESS(rc)) 962 1074 { -
trunk/src/VBox/Runtime/testcase/tstStrToNum.cpp
r93115 r96127 88 88 } while (0) 89 89 90 #define FULL_TEST(Test, Type, Fmt, Fun, iTest) \ 91 do \ 92 { \ 93 Type Result; \ 94 int rc = Fun(Test.psz, Test.uBase, &Result); \ 95 if (Result != Test.Result) \ 96 RTTestIFailed("'%s' -> " Fmt " expected " Fmt ". (%s/%u)\n", Test.psz, Result, Test.Result, #Fun, iTest); \ 97 else if (rc != Test.rc) \ 98 RTTestIFailed("'%s' -> rc=%Rrc expected %Rrc. (%s/%u)\n", Test.psz, rc, Test.rc, #Fun, iTest); \ 99 } while (0) 100 101 102 #define RUN_FULL_TESTS(aTests, Type, Fmt, Fun) \ 103 do \ 104 { \ 105 for (unsigned iTest = 0; iTest < RT_ELEMENTS(aTests); iTest++) \ 106 { \ 107 FULL_TEST(aTests[iTest], Type, Fmt, Fun, iTest); \ 108 } \ 109 } while (0) 110 90 111 int main() 91 112 { … … 104 125 { "0x0fffffffffffffff", 0, VINF_SUCCESS, 0x0fffffffffffffffULL }, 105 126 { "0x0ffffffffffffffffffffff",0, VWRN_NUMBER_TOO_BIG, 0xffffffffffffffffULL }, 127 { "0x0ffffffffffffffffffffff", 10 << 8, VINF_SUCCESS, 0x0fffffff }, 106 128 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 107 129 { "0x111111111", 0, VINF_SUCCESS, 0x111111111ULL }, … … 109 131 }; 110 132 RUN_TESTS(aTstU64, uint64_t, "%#llx", RTStrToUInt64Ex); 133 134 static const struct TstU64 aTstFullU64[] = 135 { 136 { "42", 0, VINF_SUCCESS, 42 }, 137 { "42 ", 0, VERR_TRAILING_SPACES, 42 }, 138 { "42! ", 0, VERR_TRAILING_CHARS, 42 }, 139 { "42 !", 0, VERR_TRAILING_CHARS, 42 }, 140 { "42 !", 2<<8, VINF_SUCCESS, 42 }, 141 { "42 !", 3<<8, VERR_TRAILING_SPACES, 42 }, 142 { "42 !", 4<<8, VERR_TRAILING_CHARS, 42 }, 143 { "-1", 0, VWRN_NEGATIVE_UNSIGNED, UINT64_MAX }, 144 { "-1 ", 0, VERR_TRAILING_SPACES, UINT64_MAX }, 145 { "-1 ", 2<<8, VWRN_NEGATIVE_UNSIGNED, UINT64_MAX }, 146 { "-1 ", 3<<8, VERR_TRAILING_SPACES, UINT64_MAX }, 147 { "0x0fffffffffffffff", 0, VINF_SUCCESS, 0x0fffffffffffffffULL }, 148 { "0x0ffffffffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffffffffffULL }, 149 { "0x0ffffffffffffffffffff ", 0, VERR_TRAILING_SPACES, 0xffffffffffffffffULL }, 150 { "0x0ffffffffffffffffffff! ", 0, VERR_TRAILING_CHARS, 0xffffffffffffffffULL }, 151 { "0x0ffffffffffffffffffff !", 0, VERR_TRAILING_CHARS, 0xffffffffffffffffULL }, 152 { "0x0ffffffffffffffffffff", 10 << 8, VINF_SUCCESS, 0x0fffffff }, 153 }; 154 RUN_FULL_TESTS(aTstFullU64, uint64_t, "%#llx", RTStrToUInt64Full); 111 155 112 156 static const struct TstI64 aTstI64[] = … … 153 197 { "0x07f7f7f7f7f7f7f7f7f7f7f",0, VWRN_NUMBER_TOO_BIG, 0x7f7f7f7f7f7f7f7fULL }, 154 198 { "0x0ffffffffffffffffffffff",0, VWRN_NUMBER_TOO_BIG, (int64_t)0xffffffffffffffffULL }, 199 { "0x0ffffffffffffffffffffff", 10 << 8, VINF_SUCCESS, INT64_C(0x0fffffff) }, 200 { "0x0ffffffffffffffffffffff", 18 << 8, VINF_SUCCESS, INT64_C(0x0fffffffffffffff) }, 201 { "0x0ffffffffffffffffffffff", 19 << 8, VWRN_NUMBER_TOO_BIG, -1 }, 155 202 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 156 203 { "0x111111111", 0, VINF_SUCCESS, 0x111111111ULL }, 157 204 }; 158 205 RUN_TESTS(aTstI64, int64_t, "%#lld", RTStrToInt64Ex); 206 207 static const struct TstI64 aTstI64Full[] = 208 { 209 { "1", 0, VINF_SUCCESS, 1 }, 210 { "1 ", 0, VERR_TRAILING_SPACES, 1 }, 211 { "1! ", 0, VERR_TRAILING_CHARS, 1 }, 212 { "1 !", 0, VERR_TRAILING_CHARS, 1 }, 213 { "1 !", 1<<8, VINF_SUCCESS, 1 }, 214 { "1 !", 2<<8, VERR_TRAILING_SPACES, 1 }, 215 { "1 !", 3<<8, VERR_TRAILING_CHARS, 1 }, 216 { "0xffffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, -1 }, 217 { "0xffffffffffffffff ", 0, VERR_TRAILING_SPACES, -1 }, 218 { "0xffffffffffffffff!", 0, VERR_TRAILING_CHARS, -1 }, 219 { "0xffffffffffffffff !", 18<<8, VWRN_NUMBER_TOO_BIG, -1 }, 220 { "0xffffffffffffffff !", 19<<8, VERR_TRAILING_SPACES, -1 }, 221 { "0xffffffffffffffff !", 20<<8, VERR_TRAILING_CHARS, -1 }, 222 }; 223 RUN_FULL_TESTS(aTstI64Full, int64_t, "%#lld", RTStrToInt64Full); 159 224 160 225 … … 202 267 { "0x01111111111111111111111",0, VWRN_NUMBER_TOO_BIG, 0x11111111 }, 203 268 { "0x0ffffffffffffffffffffff",0, VWRN_NUMBER_TOO_BIG, (int32_t)0xffffffff }, 269 { "0x0ffffffffffffffffffffff", 10 << 8, VINF_SUCCESS, 0x0fffffff }, 270 { "0x0ffffffffffffffffffffff", 11 << 8, VWRN_NUMBER_TOO_BIG, -1 }, 204 271 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 205 272 { "0x1111111", 0, VINF_SUCCESS, 0x01111111 }, … … 209 276 static const struct TstU32 aTstU32[] = 210 277 { 211 { "0", 0, VINF_SUCCESS, 0 }, 212 { "1", 0, VINF_SUCCESS, 1 }, 213 /// @todo { "-1", 0, VWRN_NEGATIVE_UNSIGNED, ~0 }, - no longer true. bad idea? 214 { "-1", 0, VWRN_NUMBER_TOO_BIG, ~0U }, 215 { "0x", 0, VWRN_TRAILING_CHARS, 0 }, 216 { "0x1", 0, VINF_SUCCESS, 1 }, 217 { "0x0fffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 218 { "0x0ffffffffffffffffffffff",0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 219 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 220 { "0x1111111", 0, VINF_SUCCESS, 0x1111111 }, 278 { "0", 0, VINF_SUCCESS, 0 }, 279 { "1", 0, VINF_SUCCESS, 1 }, 280 /// @todo { "-1", 0, VWRN_NEGATIVE_UNSIGNED, ~0 }, - no longer true. bad idea? 281 { "-1", 0, VWRN_NUMBER_TOO_BIG, ~0U }, 282 { "0x", 0, VWRN_TRAILING_CHARS, 0 }, 283 { "0x1", 0, VINF_SUCCESS, 1 }, 284 { "0x1 ", 0, VWRN_TRAILING_SPACES, 1 }, 285 { "0x0fffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 286 { "0x0ffffffffffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 287 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 288 { "0x1111111", 0, VINF_SUCCESS, 0x1111111 }, 221 289 }; 222 290 RUN_TESTS(aTstU32, uint32_t, "%#x", RTStrToUInt32Ex); 223 291 292 293 static const struct TstU32 aTstFullU32[] = 294 { 295 { "0", 0, VINF_SUCCESS, 0 }, 296 { "0x0fffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 297 { "0x0fffffffffffffffffffff", 0, VWRN_NUMBER_TOO_BIG, 0xffffffffU }, 298 { "asdfasdfasdf", 0, VERR_NO_DIGITS, 0 }, 299 { "42 ", 0, VERR_TRAILING_SPACES, 42 }, 300 { "42 ", 2<<8, VINF_SUCCESS, 42 }, 301 { "42! ", 0, VERR_TRAILING_CHARS, 42 }, 302 { "42! ", 2<<8, VINF_SUCCESS, 42 }, 303 { "42 !", 0, VERR_TRAILING_CHARS, 42 }, 304 { "42 !", 2<<8, VINF_SUCCESS, 42 }, 305 { "42 !", 3<<8, VERR_TRAILING_SPACES, 42 }, 306 { "42 !", 4<<8, VERR_TRAILING_CHARS, 42 }, 307 { "0x0fffffffffffffffffffff ", 0, VERR_TRAILING_SPACES, 0xffffffffU }, 308 { "0x0fffffffffffffffffffff !", 0, VERR_TRAILING_CHARS, 0xffffffffU }, 309 }; 310 RUN_FULL_TESTS(aTstFullU32, uint32_t, "%#x", RTStrToUInt32Full); 224 311 225 312 /*
Note:
See TracChangeset
for help on using the changeset viewer.