inheritance.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright Daniel Wallin 2009. Use, modification and distribution is
  2. // subject to the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef LUABIND_INHERITANCE_090217_HPP
  5. # define LUABIND_INHERITANCE_090217_HPP
  6. # include <cassert>
  7. # include <limits>
  8. # include <map>
  9. # include <memory>
  10. # include <vector>
  11. # include <luabind/typeid.hpp>
  12. # include <boost/scoped_ptr.hpp>
  13. namespace luabind { namespace detail {
  14. typedef void*(*cast_function)(void*);
  15. typedef std::size_t class_id;
  16. class_id const unknown_class = (std::numeric_limits<class_id>::max)();
  17. class class_rep;
  18. class LUABIND_API cast_graph
  19. {
  20. public:
  21. cast_graph();
  22. ~cast_graph();
  23. // `src` and `p` here describe the *most derived* object. This means that
  24. // for a polymorphic type, the pointer must be cast with
  25. // dynamic_cast<void*> before being passed in here, and `src` has to
  26. // match typeid(*p).
  27. std::pair<void*, int> cast(
  28. void* p, class_id src, class_id target
  29. , class_id dynamic_id, void const* dynamic_ptr) const;
  30. void insert(class_id src, class_id target, cast_function cast);
  31. private:
  32. class impl;
  33. boost::scoped_ptr<impl> m_impl;
  34. };
  35. // Maps a type_id to a class_id. Note that this actually partitions the
  36. // id-space into two, using one half for "local" ids; ids that are used only as
  37. // keys into the conversion cache. This is needed because we need a unique key
  38. // even for types that hasn't been registered explicitly.
  39. class LUABIND_API class_id_map
  40. {
  41. public:
  42. class_id_map();
  43. class_id get(type_id const& type) const;
  44. class_id get_local(type_id const& type);
  45. void put(class_id id, type_id const& type);
  46. private:
  47. typedef std::map<type_id, class_id> map_type;
  48. map_type m_classes;
  49. class_id m_local_id;
  50. static class_id const local_id_base;
  51. };
  52. inline class_id_map::class_id_map()
  53. : m_local_id(local_id_base)
  54. {}
  55. inline class_id class_id_map::get(type_id const& type) const
  56. {
  57. map_type::const_iterator i = m_classes.find(type);
  58. if (i == m_classes.end() || i->second >= local_id_base)
  59. return unknown_class;
  60. return i->second;
  61. }
  62. inline class_id class_id_map::get_local(type_id const& type)
  63. {
  64. std::pair<map_type::iterator, bool> result = m_classes.insert(
  65. std::make_pair(type, 0));
  66. if (result.second)
  67. result.first->second = m_local_id++;
  68. assert(m_local_id >= local_id_base);
  69. return result.first->second;
  70. }
  71. inline void class_id_map::put(class_id id, type_id const& type)
  72. {
  73. assert(id < local_id_base);
  74. std::pair<map_type::iterator, bool> result = m_classes.insert(
  75. std::make_pair(type, 0));
  76. assert(
  77. result.second
  78. || result.first->second == id
  79. || result.first->second >= local_id_base
  80. );
  81. result.first->second = id;
  82. }
  83. class class_map
  84. {
  85. public:
  86. class_rep* get(class_id id) const;
  87. void put(class_id id, class_rep* cls);
  88. private:
  89. std::vector<class_rep*> m_classes;
  90. };
  91. inline class_rep* class_map::get(class_id id) const
  92. {
  93. if (id >= m_classes.size())
  94. return 0;
  95. return m_classes[id];
  96. }
  97. inline void class_map::put(class_id id, class_rep* cls)
  98. {
  99. if (id >= m_classes.size())
  100. m_classes.resize(id + 1);
  101. m_classes[id] = cls;
  102. }
  103. template <class S, class T>
  104. struct static_cast_
  105. {
  106. static void* execute(void* p)
  107. {
  108. return static_cast<T*>(static_cast<S*>(p));
  109. }
  110. };
  111. template <class S, class T>
  112. struct dynamic_cast_
  113. {
  114. static void* execute(void* p)
  115. {
  116. return dynamic_cast<T*>(static_cast<S*>(p));
  117. }
  118. };
  119. // Thread safe class_id allocation.
  120. LUABIND_API class_id allocate_class_id(type_id const& cls);
  121. template <class T>
  122. struct registered_class
  123. {
  124. static class_id const id;
  125. };
  126. template <class T>
  127. class_id const registered_class<T>::id = allocate_class_id(typeid(T));
  128. template <class T>
  129. struct registered_class<T const>
  130. : registered_class<T>
  131. {};
  132. }} // namespace luabind::detail
  133. #endif // LUABIND_INHERITANCE_090217_HPP