parse_values.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
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         // Integer digits
00116         while(s < stop && *s >= '0' && *s <= '9')
00117         {
00118           val *= 10;
00119           val += *s - '0';
00120           ok = true;
00121           ++s;
00122         }
00123 
00124         // Fractional digits
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         // Exponetial digits
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 }

Generated on Sun Jul 30 22:55:45 2006 for Archon by  doxygen 1.4.4