00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 EnumTypeInfo.hpp 00003 00004 EnumTypeInfo.hpp - description 00005 ------------------- 00006 begin : Tue September 07 2010 00007 copyright : (C) 2010 The SourceWorks 00008 email : peter@thesourceworks.com 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 #include "../rtt-config.h" 00040 #include "Types.hpp" 00041 #include "TemplateTypeInfo.hpp" 00042 #include "TemplateConstructor.hpp" 00043 00044 namespace RTT 00045 { 00046 namespace types 00047 { 00048 00055 template<class T> 00056 struct EnumTypeInfo: public TemplateTypeInfo<T, false> 00057 { 00058 protected: 00059 static int enum_to_int(T e) 00060 { 00061 return (int) e; 00062 } 00063 00064 static T int_to_enum(int i) 00065 { 00066 return (T) i; 00067 } 00068 00069 std::map<T,std::string> to_string; 00070 typedef std::map<T,std::string> MapType; 00071 public: 00072 EnumTypeInfo(std::string type) : 00073 TemplateTypeInfo<T, false> (type) 00074 { 00075 } 00076 00077 bool installTypeInfoObject(TypeInfo* ti) { 00078 if (!Types()->type("int")) { 00079 log(Error) << "Failed to register enum <-> int conversion because type int is not known in type system."<<endlog(); 00080 return false; 00081 } else { 00082 TemplateTypeInfo<T,false>::installTypeInfoObject(ti); 00083 Types()->type("int")->addConstructor(newConstructor( 00084 &EnumTypeInfo<T>::enum_to_int, true)); 00085 } 00086 ti->addConstructor( newConstructor( &EnumTypeInfo<T>::int_to_enum, true) ); 00087 00088 // Don't delete us, we're memory-managed. 00089 return false; 00090 } 00091 00098 virtual bool composeType(base::DataSourceBase::shared_ptr source, 00099 base::DataSourceBase::shared_ptr result) const 00100 { 00101 // First, try a plain update. 00102 if (result->update(source.get())) 00103 return true; 00104 // try conversion from int to enum: 00105 internal::DataSource<int>::shared_ptr ds = 00106 internal::DataSource<int>::narrow( source.get() ); 00107 if (ds) 00108 { 00109 typename internal::AssignableDataSource<T>::shared_ptr menum = 00110 internal::AssignableDataSource<T>::narrow( source.get() ); 00111 assert(menum); 00112 menum->set( (T)ds->get() ); 00113 return true; 00114 } 00115 // try conversion from string to enum: 00116 internal::DataSource<std::string>::shared_ptr dss = 00117 internal::DataSource<std::string>::narrow( source.get() ); 00118 if (dss) 00119 { 00120 typename internal::AssignableDataSource<T>::shared_ptr menum = 00121 internal::AssignableDataSource<T>::narrow( result.get() ); 00122 assert(menum); 00123 for( typename MapType::const_iterator it = to_string.begin(); it != to_string.end(); ++it) 00124 if ( it->second == dss->get() ) { 00125 menum->set( it->first ); 00126 return true; 00127 } 00128 } 00129 // no conversion possible. 00130 return false; 00131 } 00132 00140 virtual base::DataSourceBase::shared_ptr decomposeType(base::DataSourceBase::shared_ptr source) const 00141 { 00142 // Convert enum to string 00143 typename internal::DataSource<T>::shared_ptr ds = internal::DataSource<T>::narrow( source.get() ); 00144 if ( ds ) 00145 { 00146 // if not available, just convert to int. 00147 if ( to_string.count( ds->get() ) == 0 ) { 00148 log(Warning) << "No enum-to-string mapping defined for enum " << this->getTypeName() <<". Converting to int."<<endlog(); 00149 return new internal::ValueDataSource<int>( ds->get() ); 00150 } 00151 internal::ValueDataSource<std::string>::shared_ptr vds = new internal::ValueDataSource<std::string>( to_string.find(ds->get())->second ); 00152 return vds; 00153 } 00154 // convert string to enum 00155 return base::DataSourceBase::shared_ptr(); 00156 } 00157 }; 00158 } 00159 }