00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef CGATOOLS_UTIL_PARSE_HPP_
00016 #define CGATOOLS_UTIL_PARSE_HPP_ 1
00017
00020
00021 #include "cgatools/core.hpp"
00022 #include "cgatools/util/Exception.hpp"
00023 #include <string>
00024 #include <boost/static_assert.hpp>
00025
00026 namespace cgatools { namespace util {
00027
00028 template <typename Value, bool IsSigned>
00029 struct ValueParser
00030 {
00031 static Value parse(const char* first, const char* last)
00032 {
00033
00034
00035
00036 BOOST_STATIC_ASSERT(0 == sizeof(Value));
00037 }
00038 };
00039
00040 template <typename Value>
00041 struct ValueParser<Value, true>
00042 {
00043 static Value parse(const char* first, const char* last)
00044 {
00045 if (first == last)
00046 throw Exception("failed to parse int: empty string");
00047
00048 bool neg = '-' == *first;
00049
00050 const char* current = first;
00051 if (neg)
00052 ++current;
00053
00054 if (current == last)
00055 throw Exception("failed to parse int: empty string");
00056
00057 Value val(0);
00058 Value maxVal = std::numeric_limits<Value>::max() / 10;
00059 for(; current<last; current++)
00060 {
00061 if (*current < '0' || *current > '9')
00062 throw Exception("failed to parse int: "+std::string(first, last));
00063 Value digit = *current - '0';
00064 if (val >= maxVal)
00065 {
00066 Value maxDigit = std::numeric_limits<Value>::max() % 10;
00067 if (neg && current+1 == last)
00068 maxDigit++;
00069 if (val > maxVal || digit > maxDigit)
00070 throw Exception("failed to parse int: overflow: "+std::string(first, last));
00071 }
00072 val = val*10 + digit;
00073 }
00074 if (neg)
00075 val = -val;
00076 return val;
00077 }
00078 };
00079
00080 template <typename Value>
00081 struct ValueParser<Value, false>
00082 {
00083 static Value parse(const char* first, const char* last)
00084 {
00085 if (first == last)
00086 throw Exception("failed to parse int: empty string");
00087
00088 Value val(0);
00089 Value maxVal = std::numeric_limits<Value>::max() / 10;
00090 for(const char* current=first; current<last; current++)
00091 {
00092 if (*current < '0' || *current > '9')
00093 throw Exception("failed to parse int: "+std::string(first, last));
00094 Value digit = *current - '0';
00095 if (val >= maxVal)
00096 {
00097 Value maxDigit = std::numeric_limits<Value>::max() % 10;
00098 if (val > maxVal || digit > maxDigit)
00099 throw Exception("failed to parse int: overflow: "+std::string(first, last));
00100 }
00101 val = val*10 + digit;
00102 }
00103 return val;
00104 }
00105 };
00106
00107 float parseFloat (const char* first, const char* last);
00108 double parseDouble(const char* first, const char* last);
00109
00110 template <>
00111 struct ValueParser<float, true>
00112 {
00113 static float parse(const char* first, const char* last)
00114 {
00115 return parseFloat(first, last);
00116 }
00117 };
00118
00119 template <>
00120 struct ValueParser<double, true>
00121 {
00122 static double parse(const char* first, const char* last)
00123 {
00124 return parseDouble(first, last);
00125 }
00126 };
00127
00148 template <typename Value>
00149 Value parseValue(const char* first, const char* last)
00150 {
00151 return ValueParser<Value, std::numeric_limits<Value>::is_signed>::parse(first, last);
00152 }
00153
00156 template <typename Value> Value parseValue(const char* str)
00157 {
00158 const char* strEnd = str + std::strlen(str);
00159 return parseValue<Value>(str, strEnd);
00160 }
00161
00164 template <typename Value> Value parseValue(const std::string& str)
00165 {
00166 return parseValue<Value>(str.c_str(), str.c_str()+str.length());
00167 }
00168
00169 } }
00170
00171 #endif // CGATOOLS_UTIL_PARSE_HPP_