pstrtoi.cxx (2685B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #include <string.h> 13 14 #include "ptypes.h" 15 16 17 namespace ptypes { 18 19 20 static void throw_conv(const char* p); 21 static void throw_overflow(const char* p); 22 23 24 large ptdecl stringtoi(const char* p) 25 { 26 if (p == 0) 27 return -1; 28 if (*p == 0) 29 return -1; 30 31 large r = 0; 32 do 33 { 34 char c = *p++; 35 if (c < '0' || c > '9') 36 return -1; // invalid character 37 large t = r * 10; 38 if (t < r) 39 return -1; // overflow 40 t += c - '0'; 41 if (t < r) 42 return -1; // overflow 43 r = t; 44 } while (*p != 0); 45 46 return r; 47 } 48 49 50 econv::~econv() 51 { 52 } 53 54 55 ularge ptdecl stringtoue(const char* str, int base) 56 { 57 if (str == 0) 58 throw_conv(str); 59 if (*str == 0 || base < 2 || base > 64) 60 throw_conv(str); 61 62 const char* p = str; 63 ularge result = 0; 64 65 do 66 { 67 int c = *p++; 68 69 if (c >= 'a') 70 { 71 // for the numeration bases that use '.', '/', digits and 72 // uppercase letters the letter case is insignificant. 73 if (base <= 38) 74 c -= 'a' - '9' - 1; 75 else // others use both upper and lower case letters 76 c -= ('a' - 'Z' - 1) + ('A' - '9' - 1); 77 } 78 else if (c > 'Z') 79 throw_conv(str); 80 else if (c >= 'A') 81 c -= 'A' - '9' - 1; 82 else if (c > '9') 83 throw_conv(str); 84 85 c -= (base > 36) ? '.' : '0'; 86 if (c < 0 || c >= base) 87 throw_conv(str); 88 89 ularge t = result * uint(base); 90 if (t / base != result) 91 throw_overflow(str); 92 result = t; 93 t = result + uint(c); 94 if (t < result) 95 throw_overflow(str); 96 result = t; 97 } while (*p != 0); 98 99 return result; 100 } 101 102 103 large ptdecl stringtoie(const char* str) 104 { 105 if (str == 0) 106 throw_conv(str); 107 bool neg = *str == '-'; 108 ularge result = stringtoue(str + int(neg), 10); 109 if (result > (ularge(LARGE_MAX) + uint(neg))) 110 throw_overflow(str); 111 if (neg) 112 return - large(result); 113 else 114 return large(result); 115 } 116 117 118 #ifdef _MSC_VER 119 // disable "unreachable code" warning for throw (known compiler bug) 120 # pragma warning (disable: 4702) 121 #endif 122 123 static void throw_conv(const char* p) 124 { 125 throw new econv("Invalid number: '" + string(p) + '\''); 126 } 127 128 129 static void throw_overflow(const char* p) 130 { 131 throw new econv("Out of range: '" + string(p) + '\''); 132 } 133 134 135 } 136