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