Fawkes API  Fawkes Development Version
field.cpp
00001  
00002 /***************************************************************************
00003  *  field.cpp - Interface generator field representation
00004  *
00005  *  Generated: Wed Oct 11 18:16:15 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/field.h>
00024 #include <interfaces/generator/type_checker.h>
00025 #include <interfaces/generator/exceptions.h>
00026 
00027 #include <stdlib.h>
00028 
00029 
00030 /** @class InterfaceField interfaces/generator/field.h
00031  * Interface generator internal representation of a field as parsed from
00032  * the XML template file.
00033  */
00034 
00035 
00036 /** Constructor.
00037  * @param enum_constants enumeration constants that are available and which can be
00038  * used as value type.
00039  */
00040 InterfaceField::InterfaceField(std::vector<InterfaceEnumConstant> *enum_constants)
00041 {
00042   this->enum_constants = enum_constants;
00043   length = "";
00044   length_value = 0;
00045   is_enum_type = false;
00046 }
00047 
00048 
00049 /** Get name of field.
00050  * @return name of field.
00051  */
00052 std::string
00053 InterfaceField::getName() const
00054 {
00055   return name;
00056 }
00057 
00058 
00059 /** Get type of field.
00060  * @return type of field.
00061  */
00062 std::string
00063 InterfaceField::getType() const
00064 {
00065     return type;
00066 }
00067 
00068 
00069 /** Get comment of field.
00070  * @return comment of field.
00071  */
00072 std::string
00073 InterfaceField::getComment() const
00074 {
00075     return comment;
00076 }
00077 
00078 
00079 /** Get type as used for accessor methods of class.
00080  * @return accessor type
00081  */
00082 std::string
00083 InterfaceField::getAccessType() const
00084 {
00085   if (type == "string") {
00086     return "char *";
00087   } else {
00088     if ( length != "" ) {
00089       if (type == "byte") {
00090         return "uint8_t *";
00091       } else if (type == "float" || type == "double" || type == "bool" || is_enum_type) {
00092         return type + " *";
00093       } else {
00094         return type + "_t *";
00095       }
00096     } else {
00097       if (type == "byte") {
00098         return "uint8_t";
00099       } else if (type == "float" || type == "double" || type == "bool" || is_enum_type) {
00100         return type;
00101       } else {
00102         return type + "_t";
00103       }
00104     }
00105   }
00106 }
00107 
00108 
00109 /** Get non-array accessor type.
00110  * @return accessor type
00111  */
00112 std::string
00113 InterfaceField::getPlainAccessType() const
00114 {
00115   if (type == "string") {
00116     return "char *";
00117   } else if (type == "byte") {
00118     return "uint8_t";
00119   } else if (type == "float" || type == "double" || type == "bool" || is_enum_type) {
00120     return type;
00121   } else {
00122     return type + "_t";
00123   }
00124 }
00125 
00126 
00127 /** Get type used to formulate struct.
00128  * @return struct type
00129  */
00130 std::string
00131 InterfaceField::getStructType() const
00132 {
00133   if (type == "string") {
00134     return "char";
00135   } else if (type == "byte") {
00136     return "uint8_t";
00137   } else if (type == "float" || type == "double" || type == "bool") {
00138     return type;
00139   } else if (is_enum_type) {
00140     return "int32_t";
00141   } else {
00142     return type + "_t";
00143   }
00144 }
00145 
00146 
00147 /** Check if type is an enum type.
00148  * @return true if the type of this field is an enum type, false otherwise
00149  */
00150 bool
00151 InterfaceField::isEnumType() const
00152 {
00153   return is_enum_type;
00154 }
00155 
00156 /** Get field length.
00157  * @return field length
00158  */
00159 std::string
00160 InterfaceField::getLength() const
00161 {
00162   return length;
00163 }
00164 
00165 
00166 /** Get length value.
00167  * This gives the length of the value as a uint instead of a string
00168  * which is sufficient for the generation of the interface but may not
00169  * be sufficient for more elaborated usage.
00170  * @return length of the value
00171  */
00172 unsigned int
00173 InterfaceField::getLengthValue() const
00174 {
00175   return length_value;
00176 }
00177 
00178 
00179 /** Get valid for time.
00180  * @return valid for time
00181  */
00182 std::string
00183 InterfaceField::getValidFor() const
00184 {
00185   return validfor;
00186 }
00187 
00188 
00189 /** Get default value.
00190  * @return default value
00191  */
00192 std::string
00193 InterfaceField::getDefaultValue() const
00194 {
00195   return default_value;
00196 }
00197 
00198 
00199 /** Get flags.
00200  * @return flags.
00201  */
00202 std::vector<std::string>
00203 InterfaceField::getFlags() const
00204 {
00205   return flags;
00206 }
00207 
00208 
00209 /** Set type of field.
00210  * @param type new type of field.
00211  */
00212 void
00213 InterfaceField::setType(const std::string &type)
00214 {
00215   is_enum_type = false;
00216   if ( enum_constants != NULL ) {
00217     std::vector<InterfaceEnumConstant>::iterator i;
00218     for (i = enum_constants->begin(); i != enum_constants->end(); ++i) {
00219       if ( type == (*i).get_name() ) {
00220         is_enum_type = true;
00221       }
00222     }
00223   }
00224   this->type = type;
00225 }
00226 
00227 
00228 /** Set name of field.
00229  * @param name new name of field.
00230  */
00231 void
00232 InterfaceField::setName(const std::string &name)
00233 {
00234   this->name = name;
00235 }
00236 
00237 
00238 /** Set comment of field.
00239  * @param comment new comment of field.
00240  */
00241 void
00242 InterfaceField::setComment(const std::string &comment)
00243 {
00244   this->comment = comment;
00245 }
00246 
00247 
00248 /** Set length of field.
00249  * @param length set length of field.
00250  */
00251 void
00252 InterfaceField::setLength(const std::string &length)
00253 {
00254   this->length_value = (unsigned int)atoi(length.c_str());
00255   this->length = length;
00256 }
00257 
00258 
00259 /** Set valid for time.
00260  * @param validfor new valid for time
00261  */
00262 void
00263 InterfaceField::setValidFor(const std::string &validfor)
00264 {
00265   this->validfor = validfor;
00266 }
00267 
00268 
00269 /** Set default value.
00270  * @param default_value new default value
00271  */
00272 void
00273 InterfaceField::setDefaultValue(const std::string &default_value)
00274 {
00275   this->default_value = default_value;
00276 }
00277 
00278 
00279 /** Set flags.
00280  * @param flags new flags of field
00281  */
00282 void
00283 InterfaceField::setFlags(const std::vector<std::string> &flags)
00284 {
00285   this->flags = flags;
00286 }
00287 
00288 
00289 /** Tokenize given string.
00290  * @param str tsring to tokenize
00291  * @param tokens vector where result will be stored
00292  * @param delimiters string with delimiters.
00293  */
00294 void
00295 InterfaceField::tokenize(const std::string&   str,
00296                          std::vector<std::string>& tokens,
00297                          const std::string&   delimiters)
00298 {
00299   // Skip delimiters at beginning.
00300   std::string::size_type last_pos = str.find_first_not_of(delimiters, 0);
00301   // Find first "non-delimiter".
00302   std::string::size_type pos      = str.find_first_of(delimiters, last_pos);
00303 
00304   while (std::string::npos != pos || std::string::npos != last_pos) {
00305     // Found a token, add it to the vector.
00306     tokens.push_back(str.substr(last_pos, pos - last_pos));
00307     // Skip delimiters.  Note the "not_of"
00308     last_pos = str.find_first_not_of(delimiters, pos);
00309     // Find next "non-delimiter"
00310     pos = str.find_first_of(delimiters, last_pos);
00311   }
00312 }
00313 
00314 
00315 /** Set attribute.
00316  * @param attr_name attribute name
00317  * @param attr_value attribute value.
00318  */
00319 void
00320 InterfaceField::setAttribute(const std::string &attr_name, const std::string &attr_value)
00321 {
00322   if ( attr_name == "name" ) {
00323     setName(attr_value);
00324   } else if ( attr_name == "type" ) {
00325     setType(attr_value);
00326   } else if ( attr_name == "length" ) {
00327     setLength(attr_value);
00328   } else if ( attr_name == "validfor" ) {
00329     setValidFor(attr_value);
00330   } else if ( attr_name == "default" ) {
00331     setDefaultValue(attr_value);
00332   } else if ( attr_name == "flags" ) {
00333     tokenize(attr_value, flags, ",");
00334   }
00335 }
00336 
00337 
00338 /** Assert validity.
00339  * Calling valid() acts like an assertion. An Exception is thrown if something is wrong.
00340  * @exception InterfaceGeneratorInvalidTypeException thrown if InterfaceDataTypeChecker
00341  * reports invalid type.
00342  * @exception InterfaceGeneratorInvalidValueException thrown if any supplied value is
00343  * illegal.
00344  * @exception InterfaceGeneratorInvalidFlagException thrown if invalid flag has been
00345  * supplied.
00346  */
00347 void
00348 InterfaceField::valid()
00349 {
00350   if ( ! InterfaceDataTypeChecker::validType(type, enum_constants) ) {
00351     throw InterfaceGeneratorInvalidTypeException("field", name.c_str(), type.c_str());
00352   }
00353   if ( (name.length() == 0) || (name.find(" ") != std::string::npos) ) {
00354     throw InterfaceGeneratorInvalidValueException("name", "string", "name must not contain spaces");
00355   }
00356   if ( (length.length() > 0) && ! InterfaceDataTypeChecker::validValue("uint32", length) ) {
00357     throw InterfaceGeneratorInvalidValueException("length", "uint32", length.c_str());
00358   }
00359   if ( (validfor.length() > 0) && ! InterfaceDataTypeChecker::validValue("uint32", validfor) ) {
00360     throw InterfaceGeneratorInvalidValueException("validfor", "uint32", validfor.c_str());
00361   }
00362   if ( (default_value.length() > 0) &&
00363        ! InterfaceDataTypeChecker::validValue(type, default_value) ) {
00364     throw InterfaceGeneratorInvalidValueException("default", type.c_str(), validfor.c_str());
00365   }
00366   for (std::vector<std::string>::iterator i = flags.begin(); i != flags.end(); ++i) {
00367     if ( *i != "changed_indicator" ) {
00368       throw InterfaceGeneratorInvalidFlagException(name.c_str(), (*i).c_str());
00369     }
00370   }
00371   /*
00372   if ( (type == "char") && (length.length() == 0) ) {
00373     throw InterfaceGeneratorMissingAttributeException(name.c_str(), type.c_str(), "length");
00374   }
00375   */
00376 }
00377 
00378 
00379 /** Check order of two elements.
00380  * The overall order is like the following:
00381  * 1. unsigned int
00382  * 2. int
00383  * 3. unsigned long int
00384  * 4. long int
00385  * 5. float
00386  * 6. double
00387  * 7. bool
00388  * 8. byte
00389  * 9. char *
00390  * @param f field to compare to
00391  * @return true, if current instance is small than f, false otherwise
00392  */
00393 bool
00394 InterfaceField::operator< (const InterfaceField &f) const
00395 {
00396   if ( (type == "unsigned int") ) {
00397     return (f.type != "unsigned int");
00398 
00399   } else if ( type == "int" ) {
00400     return ( (f.type != "int") &&
00401              (f.type != "unsigned int") );
00402 
00403 
00404   } else if ( type == "unsigned long int" ) {
00405     return ( (f.type != "unsigned long int") &&
00406              (f.type != "unsigned int") &&
00407              (f.type != "int") );
00408 
00409   } else if ( type == "long int" ) {
00410     return ( (f.type != "long int") &&
00411              (f.type != "unsigned int") &&
00412              (f.type != "int") &&
00413              (f.type != "unsigned long int") );
00414 
00415   } else if ( type == "float" ) {
00416     return ( (f.type != "float") &&
00417              (f.type != "unsigned int") &&
00418              (f.type != "int") );
00419 
00420   } else if ( type == "double" ) {
00421     return ( (f.type != "double") &&  
00422              (f.type != "unsigned int") &&
00423              (f.type != "int") &&
00424              (f.type != "float") );
00425 
00426   } else if ( type == "bool" ) {
00427     return ( (f.type != "bool") &&
00428              (f.type != "double") &&  
00429              (f.type != "unsigned int") &&
00430              (f.type != "int") &&
00431              (f.type != "float") );
00432 
00433   } else if ( type == "byte" ) {
00434     return ( (f.type != "byte") &&
00435              (f.type != "bool") &&
00436              (f.type != "double") &&  
00437              (f.type != "unsigned int") &&
00438              (f.type != "int") &&
00439              (f.type != "float") );
00440 
00441   } else {
00442     // char or unknown, char is always last and thus >=
00443     return false;
00444   }
00445 }