Sunday, May 22, 2011

rtti to traits for auto uuiding classes

There are times when you want automatically UID or index a class. The rtti is string based and I am assuming that simple Hashing of of that string is not sufficient. So here is a quick hack up of trait class to achieve the result.

#include <iostream>
#include <stdint.h>
#include <map>
#include <typeinfo>

class RttiCasterBase
{
private:
  class RttiRegFactory
  {
  private:
    typedef std::map<std::string, uint32_t> RttiIDMap;
    
    //0 is the bad marker..
    uint32_t g_uid;
    RttiIDMap rttiIDMap;
    
    RttiRegFactory() :
      g_uid(1)
    {}
    
  public:
    static RttiRegFactory& instance()
    {
      static RttiRegFactory instance_;
      return instance_;
    }
    
    uint32_t getID(std::string rttiName)
    {
      if (rttiIDMap.find(rttiName) != rttiIDMap.end())
 return rttiIDMap[rttiName];
      rttiIDMap[rttiName] = g_uid;
      return g_uid++;
    }
  };
protected:
  static uint32_t  lookup(std::string rttiID)
  {
    return RttiRegFactory::instance().getID(rttiID);
  }
  
public:
  RttiCasterBase() {}
  virtual ~RttiCasterBase() {}
  
  virtual uint32_t      uid() = 0;
  virtual std::size_t   size() = 0;
  virtual std::string   rttiID() = 0;
};

template<typename T>
class RttiCasterImp : public RttiCasterBase
{
public:
  typedef T Type;
  uint32_t uid_;
  
  RttiCasterImp() :
    RttiCasterBase()
  {
    uid_ = RttiCasterBase::lookup(typeid(T).name());
  }
  
  ~RttiCasterImp() {}

  virtual uint32_t uid()
  {
    return uid_;
  }
  
  virtual std::size_t size()
  {
    return sizeof(T);
  }
  
  virtual std::string   rttiID()
  {
    return typeid(T).name();
  }
  
  T* cast(void* buf)
  {
    return reinterpret_cast<T*>(buf);
  }
  
  void print(std::ostream& out)
  {
    out << "uid:  "   << uid()    << std::endl
 << "size: "   << size()   << std::endl
 << "rttiID: " << rttiID() << std::endl
 << std::endl;
  }
};

class A {};
class B { int var; };
class C { char stuff[10]; };

int main(int argc, char const * const *argv)
{
  RttiCasterImp<A> InfoA;
  RttiCasterImp<B> InfoB;
  RttiCasterImp<C> InfoC;
  RttiCasterImp<B> InfoD;
  
  InfoA.print(std::cout);
  InfoB.print(std::cout);
  InfoC.print(std::cout);       
  InfoD.print(std::cout);       
}

Output looks like:
$ a.exe
uid:  1
size: 1
rttiID: 1A

uid:  2
size: 4
rttiID: 1B

uid:  3
size: 10
rttiID: 1C

uid:  2
size: 4
rttiID: 1B

No comments:

Post a Comment