$search
00001 #ifndef TYPELIB_MEMORY_LAYOUT_HH 00002 #define TYPELIB_MEMORY_LAYOUT_HH 00003 00004 #include <stdexcept> 00005 #include <typelib/typevisitor.hh> 00006 #include <vector> 00007 #include <boost/static_assert.hpp> 00008 00009 namespace Typelib 00010 { 00013 struct NoLayout : public std::runtime_error 00014 { 00015 NoLayout(Type const& type, std::string const& reason) 00016 : std::runtime_error("there is no memory layout for type " + type.getName() + ": " + reason) { } 00017 }; 00018 00022 struct UnknownLayoutBytecode : public std::runtime_error 00023 { 00024 UnknownLayoutBytecode() : std::runtime_error("found an unknown marshalling bytecode operation") { } 00025 }; 00026 00027 // This is needed because the FLAG_CONTAINER descriptor is followed by a 00028 // pointer on a Container instance 00029 BOOST_STATIC_ASSERT((sizeof(size_t) == sizeof(void*))); 00030 00031 typedef std::vector<size_t> MemoryLayout; 00032 00039 namespace MemLayout 00040 { 00048 enum Operations { 00049 FLAG_MEMCPY, 00050 FLAG_ARRAY, 00051 FLAG_CONTAINER, 00052 FLAG_SKIP, 00053 FLAG_END 00054 }; 00055 00062 class Visitor : public TypeVisitor 00063 { 00064 private: 00065 MemoryLayout& ops; 00066 bool accept_pointers; 00067 bool accept_opaques; 00068 size_t current_op; 00069 size_t current_op_count; 00070 bool merge_skip_copy; 00071 00072 protected: 00073 void push_current_op(); 00074 void skip(size_t count); 00075 void memcpy(size_t count); 00076 void add_generic_op(size_t op, size_t count); 00077 bool generic_visit(Type const& value); 00078 bool visit_ (Numeric const& type); 00079 bool visit_ (Enum const& type); 00080 bool visit_ (Array const& type); 00081 bool visit_ (Container const& type); 00082 bool visit_ (Compound const& type); 00083 bool visit_ (Pointer const& type); 00084 bool visit_ (OpaqueType const& type); 00085 00086 void merge_skips_and_copies(); 00087 00088 public: 00089 Visitor(MemoryLayout& ops, bool accept_pointers = false, bool accept_opaques = false); 00090 00091 void apply(Type const& type, bool merge_skip_copy = true, bool remove_trailing_skips = true); 00092 }; 00093 00100 MemoryLayout::const_iterator skip_block( 00101 MemoryLayout::const_iterator begin, 00102 MemoryLayout::const_iterator end); 00103 } 00104 00122 inline MemoryLayout layout_of(Type const& t, bool accept_pointers = false, bool accept_opaques = false, bool merge_skip_copy = true, bool remove_trailing_skips = true) 00123 { 00124 MemoryLayout ret; 00125 MemLayout::Visitor visitor(ret, accept_pointers, accept_opaques); 00126 visitor.apply(t, merge_skip_copy, remove_trailing_skips); 00127 return ret; 00128 } 00129 } 00130 00131 #endif 00132