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 00008 namespace Typelib 00009 { 00010 struct NoLayout : public std::runtime_error 00011 { 00012 NoLayout(Type const& type, std::string const& reason) 00013 : std::runtime_error("there is no memory layout for type " + type.getName() + ": " + reason) { } 00014 }; 00015 00016 struct UnknownLayoutBytecode : public std::runtime_error 00017 { 00018 UnknownLayoutBytecode() : std::runtime_error("found an unknown marshalling bytecode operation") { } 00019 }; 00020 00021 // This is needed because the FLAG_CONTAINER descriptor is followed by a 00022 // pointer on a Container instance 00023 BOOST_STATIC_ASSERT((sizeof(size_t) == sizeof(void*))); 00024 00025 typedef std::vector<size_t> MemoryLayout; 00026 00033 namespace MemLayout 00034 { 00042 enum Operations { 00043 FLAG_MEMCPY, 00044 FLAG_ARRAY, 00045 FLAG_CONTAINER, 00046 FLAG_SKIP, 00047 FLAG_END 00048 }; 00049 00050 /* This visitor swaps the endianness of the given value in-place */ 00051 class Visitor : public TypeVisitor 00052 { 00053 private: 00054 MemoryLayout& ops; 00055 bool accept_pointers; 00056 size_t current_memcpy; 00057 00058 protected: 00059 void push_current_memcpy(); 00060 void skip(size_t count); 00061 bool generic_visit(Type const& value); 00062 bool visit_ (Numeric const& type); 00063 bool visit_ (Enum const& type); 00064 bool visit_ (Array const& type); 00065 bool visit_ (Container const& type); 00066 bool visit_ (Compound const& type); 00067 bool visit_ (Pointer const& type); 00068 bool visit_ (OpaqueType const& type); 00069 00070 public: 00071 Visitor(MemoryLayout& ops, bool accept_pointers = false); 00072 00073 void apply(Type const& type); 00074 }; 00075 00077 MemoryLayout::const_iterator skip_block( 00078 MemoryLayout::const_iterator begin, 00079 MemoryLayout::const_iterator end); 00080 } 00081 00082 inline MemoryLayout layout_of(Type const& t, bool accept_pointers = false) 00083 { 00084 MemoryLayout ret; 00085 MemLayout::Visitor visitor(ret, accept_pointers); 00086 visitor.apply(t); 00087 return ret; 00088 } 00089 } 00090 00091 #endif 00092