plaintext/plugin_impl/interfaces_utils.h

Go to the documentation of this file.
00001 /*
00002  * File Name: interfaces_utils.h
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-plaintext.
00007  *
00008  * uds-plugin-plaintext is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-plaintext is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #ifndef INTERFACE_UTILS_H_
00028 #define INTERFACE_UTILS_H_
00029 
00030 #include <typeinfo>
00031 #include <cassert>
00032 #include <string>
00033 #include <vector>
00034 #include <map>
00035 #include <algorithm>
00036 
00037 #include "log.h"
00038 
00039 namespace utils
00040 {
00041 
00042 const unsigned int MAX_OBJECTS    = 20;     // max. instances for any ..Impl class
00043 const unsigned int MAX_INTERFACES = 13;     // max. interfaces on any ..Impl object
00044 
00045 /// @brief The interface entry base class.
00046 class InterfaceBase
00047 {
00048 public:
00049     InterfaceBase() {};
00050     virtual ~InterfaceBase(){} ;
00051     virtual bool is_name_equal(const char *name) = 0;
00052     virtual void * get_pointer() = 0;
00053 };
00054 
00055 /// @brief Every InterfaceEntry stores the necessary information related
00056 /// to a interface, such as:
00057 /// - Interface name.
00058 /// - Interface pointer value.
00059 template<typename T>
00060 class InterfaceEntry : public InterfaceBase
00061 {
00062 public:
00063     InterfaceEntry(T *p) 
00064         : ptr(p)
00065     { 
00066     }
00067 
00068     ~InterfaceEntry()
00069     {
00070     }
00071 
00072     bool is_name_equal(const char * name)
00073     {
00074         if (name_.size() <= 0)
00075         {
00076             name_ = typeid(T).name();
00077             std::string::size_type start = name_.find("IPlugin");
00078             if (start != std::string::npos)
00079             {
00080                 name_ = name_.substr(start);
00081             }
00082             else
00083             {
00084                 name_.clear();
00085             }
00086         }
00087         return name_ == name;
00088     }
00089 
00090     virtual void * get_pointer()
00091     { 
00092         return ptr; 
00093     }
00094 
00095 private:
00096     std::string name_;  ///< The interface name.
00097     T * ptr;            ///< The casted interface pointer.
00098 };
00099 
00100 /// @brief The InterfaceTable contains a list of interfaces. From this class
00101 /// caller can add and query a given interface.
00102 class InterfaceTable
00103 {
00104 public:
00105     InterfaceTable()
00106     {
00107     }
00108 
00109     ~InterfaceTable()
00110     {
00111         clear();
00112     }
00113 
00114 public:
00115     template <class T>
00116     void add_entry(T * ptr)
00117     {
00118         interfaces.push_back(new InterfaceEntry<T>(ptr));
00119         unsigned int size = interfaces.size();
00120         if (size > MAX_INTERFACES)
00121         {
00122             ERRORPRINTF("Too many interfaces for class %s: interfaces.size [%u] max [%u]",
00123                         typeid(T).name(), size, MAX_INTERFACES);
00124         }
00125     }
00126 
00127     bool query_interface(const char * name, void **return_ptr)
00128     {
00129         Iter begin = interfaces.begin();
00130         Iter end   = interfaces.end();
00131         for(Iter it = begin; it != end; ++it)
00132         {
00133             if ((*it)->is_name_equal(name))
00134             {
00135                 *return_ptr = (*it)->get_pointer();
00136                 return true;
00137             }
00138         }
00139         // This could happen when caller wants to query a optional
00140         // interface. Should not use assert here.
00141         return false;
00142     }
00143 
00144     template <class T>
00145     bool contain_interface(T *ptr)
00146     {
00147         Iter begin = interfaces.begin();
00148         Iter end   = interfaces.end();
00149         for(Iter it = begin; it != end; ++it)
00150         {
00151             if (ptr == (*it)->get_pointer())
00152             {
00153                 return true;
00154             }
00155         }
00156         return false;
00157     }
00158 
00159 private:
00160     void clear()
00161     {
00162         Iter begin = interfaces.begin();
00163         Iter end   = interfaces.end();
00164         for(Iter it = begin; it != end; ++it)
00165         {
00166             delete (*it);
00167         }
00168         interfaces.clear();
00169     }
00170 
00171 private:
00172     typedef std::vector<InterfaceBase *> Interfaces;
00173     typedef std::vector<InterfaceBase *>::iterator Iter;
00174     Interfaces interfaces;
00175 };
00176 
00177 /// @brief This class enables caller to search between interface and object.
00178 /// It can store objects of the same class.
00179 template <typename T>
00180 class ObjectTable
00181 {
00182 public:
00183     ObjectTable(){}
00184     ~ObjectTable()
00185     {
00186         unsigned int size = table_.size();
00187         if (size != 0)
00188         {
00189             ERRORPRINTF("ObjectTable for class %s not empty: size [%u]",
00190                         typeid(T).name(), size);
00191         }
00192     }
00193 
00194 public:
00195 
00196     /// @brief Put object into object table. Extract the interface pointer
00197     /// from object. Caller should make sure the static_cast<Arg *>(object)
00198     /// is OK.
00199     template <typename Arg>
00200     bool add_interface(T *object)
00201     {
00202         TableIter iter = table_.find(object);
00203         if (iter != table_.end())
00204         {
00205             iter->second->add_entry(static_cast<Arg *>(object));
00206         }
00207         else
00208         {
00209             InterfaceTablePtr ptr = new InterfaceTable;
00210             ptr->add_entry<Arg>(static_cast<Arg *>(object));
00211             table_[object] = ptr;
00212             unsigned int size = table_.size();
00213             if (size > MAX_OBJECTS)
00214             {
00215                 ERRORPRINTF("Too many objects for class %s: ObjectTable.size [%u] max [%u]",
00216                             typeid(T).name(), size, MAX_OBJECTS);
00217             }
00218         }
00219         return true;
00220     }
00221 
00222     bool query_interface(T * object, const char *name, void **return_ptr)
00223     {
00224         TableIter iter = table_.find(object);
00225         if (iter != table_.end())
00226         {
00227             return iter->second->query_interface(name, return_ptr);
00228         }
00229         return false;
00230     }
00231 
00232     /// @brief Remove the object from object table.
00233     bool remove(T * object)
00234     {
00235         TableIter iter = table_.find(object);
00236         if (iter != table_.end())
00237         {
00238             delete iter->second;
00239             table_.erase(iter);
00240             return true;
00241         }
00242         return false;
00243     }
00244 
00245     /// @brief Retrieve object from interface poiner.
00246     template <typename Arg>
00247     T * get_object(Arg * arg)
00248     {
00249         TableIter begin = table_.begin();
00250         TableIter end   = table_.end();
00251         for(TableIter iter = begin; iter != end; ++iter)
00252         {
00253             if (iter->second->contain_interface(arg))
00254             {
00255                 return iter->first;
00256             }
00257         }
00258         assert(false);
00259         return 0;
00260     }
00261 
00262 
00263 private:
00264     typedef InterfaceTable * InterfaceTablePtr;
00265     typedef std::map<T *, InterfaceTablePtr> Table;
00266     typedef typename std::map<T *, InterfaceTablePtr>::iterator TableIter;
00267     Table table_;
00268 
00269 };
00270 
00271 };  // namespace utils
00272 
00273 
00274 #endif
00275 
Generated by  doxygen 1.6.2-20100208