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_