Fawkes API
Fawkes Development Version
|
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 }