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