00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ctype.h>
00021 #include <string.h>
00022 #include <math.h>
00023
00024 #include <archon/util/parse_values.H>
00025
00026 namespace Archon
00027 {
00028 namespace Utilities
00029 {
00030 namespace ParseValues
00031 {
00041 static bool keywordCompare(const char *s, const char *stop,
00042 const char *lowercaseKeyword)
00043 {
00044 while(s<stop && *lowercaseKeyword && *reinterpret_cast<const unsigned char *>(lowercaseKeyword) == tolower(*reinterpret_cast<const unsigned char *>(s)))
00045 ++s, ++lowercaseKeyword;
00046 return s==stop && !*lowercaseKeyword;
00047 }
00048
00049 bool parseBoolean(bool versatile, const char *s, const char *stop) throw(ParseException)
00050 {
00051 if(!stop) stop = s + strlen(s);
00052 if(s == stop) ARCHON_THROW1(ParseException, "No boolean value");
00053 if(keywordCompare(s, stop, "true")) return true;
00054 if(keywordCompare(s, stop, "false")) return false;
00055 if(versatile)
00056 {
00057 if(keywordCompare(s, stop, "y")) return true;
00058 if(keywordCompare(s, stop, "n")) return false;
00059 if(keywordCompare(s, stop, "yes")) return true;
00060 if(keywordCompare(s, stop, "no")) return false;
00061 if(keywordCompare(s, stop, "on")) return true;
00062 if(keywordCompare(s, stop, "off")) return false;
00063 try { return parseInteger(false, s, stop); }
00064 catch(ParseException &) {}
00065 }
00066 ARCHON_THROW1(ParseException,
00067 "\"" + string(s, stop-s) +
00068 "\" is an invalid boolean value");
00069 }
00070
00071 int parseInteger(bool acceptSign, const char *s, const char *stop) throw(ParseException)
00072 {
00073 if(!stop) stop = s + strlen(s);
00074 if(s == stop) ARCHON_THROW1(ParseException,
00075 "No integer value");
00076
00077 bool neg = false;
00078
00079 if(acceptSign)
00080 {
00081 if(*s == '+') ++s;
00082 else if(*s == '-') ++s, neg = true;
00083 }
00084
00085 int val = 0;
00086 while(s < stop && *s >= '0' && *s <= '9')
00087 {
00088 val *= 10;
00089 val += *s - '0';
00090 ++s;
00091 }
00092
00093 if(s != stop)
00094 ARCHON_THROW1(ParseException,
00095 "\"" + string(s, stop-s) + "\" is an invalid " +
00096 (acceptSign ? "integer value" :
00097 "unsigned integer value"));
00098
00099 return neg ? -val : val;
00100 }
00101
00102 double parseDouble(const char *s, const char *stop) throw(ParseException)
00103 {
00104 if(!stop) stop = s + strlen(s);
00105 if(s == stop) ARCHON_THROW1(ParseException,
00106 "No double value");
00107
00108 bool neg = false;
00109 if(*s == '+') ++s;
00110 else if(*s == '-') ++s, neg = true;
00111
00112 double val = 0;
00113 bool ok = false;
00114
00115
00116 while(s < stop && *s >= '0' && *s <= '9')
00117 {
00118 val *= 10;
00119 val += *s - '0';
00120 ok = true;
00121 ++s;
00122 }
00123
00124
00125 if(s < stop && *s == '.')
00126 {
00127 ++s;
00128 double frac = 1;
00129 while(s < stop && *s >= '0' && *s <= '9')
00130 {
00131 frac /= 10;
00132 val += (*s - '0')*frac;
00133 ok = true;
00134 ++s;
00135 }
00136 }
00137
00138 if(!ok) ARCHON_THROW1(ParseException,
00139 "\"" + string(s, stop-s) +
00140 "\" is an invalid double value");
00141
00142
00143 if(s < stop && (*s == 'e' || *s == 'E'))
00144 val *= pow(10.0, parseInteger(true, ++s, stop));
00145 else
00146 if(s != stop) ARCHON_THROW1(ParseException,
00147 "\"" + string(s, stop-s) +
00148 "\" is an invalid double value");
00149
00150 return neg ? -val : val;
00151 }
00152
00153 string parseString(const char *s, const char *stop) throw(ParseException)
00154 {
00155 if(!stop) stop = s + strlen(s);
00156 if(s == stop) ARCHON_THROW1(ParseException,
00157 "No string value");
00158
00159 return string(s, stop-s);
00160 }
00161 }
00162 }
00163 }