Fawkes API  Fawkes Development Version
type_checker.cpp
00001  
00002 /***************************************************************************
00003  *  type_checker.cpp - Interface generator type checker
00004  *
00005  *  Generated: Wed Oct 11 15:39:10 2006
00006  *  Copyright  2006  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include <interfaces/generator/type_checker.h>
00024 #include <interfaces/generator/exceptions.h>
00025 #include <core/exception.h>
00026 
00027 #include <cstdlib>
00028 #include <climits>
00029 #include <cmath>
00030 #include <cerrno>
00031 
00032 // request setting of INT8_MAX etc. constants
00033 #ifndef __STDC_LIMIT_MACROS
00034 #define __STDC_LIMIT_MACROS
00035 #endif
00036 #include <stdint.h>
00037 
00038 /** @class InterfaceDataTypeChecker <interfaces/generator/type_checker.h>
00039  * Type checker for interface types.
00040  * This classed is used by the generator to decide if a supplied type is
00041  * correct and in the case of constants if the supplied value matches the
00042  * field type.
00043  *
00044  * Valid types are:
00045  * - int
00046  * - long int
00047  * - unsigned int
00048  * - unsigned long int
00049  * - bool
00050  * - float
00051  * - double
00052  * - byte (unsigned 8-bit number)
00053  * - string
00054  */
00055 
00056 
00057 /** Check type validity.
00058  * @param type type string to check
00059  * @param enum_constants an optional vector of enumeration constants that are used for
00060  * type validation.
00061  * @return true, if type is valid, false otherwise
00062  */
00063 bool
00064 InterfaceDataTypeChecker::validType(const std::string &type, std::vector<InterfaceEnumConstant> *enum_constants)
00065 {
00066   if ( (type == "int8") ||
00067        (type == "int16") ||
00068        (type == "int32") ||
00069        (type == "int64") ||
00070        (type == "uint8") ||
00071        (type == "uint16") ||
00072        (type == "uint32") ||
00073        (type == "uint64") ||
00074        (type == "bool") ||
00075        (type == "char") ||
00076        (type == "float") ||
00077        (type == "byte") ||
00078        (type == "string") ||
00079        (type == "double") ) {
00080     return true;
00081   } else if ( enum_constants != NULL ) {
00082     std::vector<InterfaceEnumConstant>::iterator i;
00083     for (i = enum_constants->begin(); i != enum_constants->end(); ++i) {
00084       if ( type == (*i).get_name() ) {
00085         return true;
00086       }
00087     }
00088     return false;
00089   } else {
00090     return false;
00091   }
00092 }
00093 
00094 
00095 /** Check value validity for given type.
00096  * @param type type if value
00097  * @param value value to check
00098  * @return true, if value is valid for type, false otherwise
00099  */
00100 bool
00101 InterfaceDataTypeChecker::validValue(const std::string &type, const std::string &value)
00102 {
00103   if (type.find("int") != std::string::npos) {
00104     char *endptr;
00105     long long int rv = strtoll(value.c_str(), &endptr, 10);
00106     if ( ((rv == LLONG_MIN) || (rv == LLONG_MAX)) && (errno == ERANGE) ) {
00107       throw fawkes::Exception("Could not convert value string '%s' to "
00108                               "long long int", value.c_str());
00109     }
00110     if ( (endptr != NULL) && (endptr[0] == '\0')) {
00111       if (type == "uint8") {
00112         return (rv >= 0) && (rv <= UINT8_MAX);
00113       } else if (type == "uint16") {
00114         return (rv >= 0) && (rv <= UINT16_MAX);
00115       } else if (type == "uint32") {
00116         return (rv >= 0) && (rv <= UINT32_MAX);
00117       } else if (type == "uint64") {
00118         return (rv >= 0) && ((uint64_t)rv <= UINT64_MAX);
00119       } else if (type == "int8") {
00120         return (rv >= INT8_MIN) && (rv <= INT8_MAX);
00121       } else if (type == "int16") {
00122         return (rv >= INT16_MIN) && (rv <= INT16_MAX);
00123       } else if (type == "int32") {
00124         return (rv >= INT32_MIN) && (rv <= INT32_MAX);
00125       } else if (type == "int64") {
00126         return (rv >= INT64_MIN) && (rv <= INT64_MAX);
00127       } else {
00128         return false;
00129       }
00130     } else {
00131       return false;
00132     }
00133   } else if ( type == "bool" ) {
00134     return ( (value == "true") ||
00135              (value == "false") ||
00136              (value == "yes") ||
00137              (value == "no") ||
00138              (value == "0") ||
00139              (value == "1") );
00140   } else if ( (type == "float") ||
00141               (type == "double") ) {
00142     char *endptr;
00143     float rv = strtod(value.c_str(), &endptr);
00144     if ((rv == HUGE_VAL) || (rv == -HUGE_VAL)) {
00145       throw fawkes::Exception("Could not convert string '%s' to float", value.c_str());
00146     }
00147     return ((endptr != NULL) && (endptr[0] == '\0'));
00148   } else if ( type == "string" ) {
00149     return true;
00150   } else {
00151     return false;
00152   }
00153 }