]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/persistence/persistent_contexts.cpp
testing new non-autotools build system
[chaz/yoink] / src / stlplus / persistence / persistent_contexts.cpp
diff --git a/src/stlplus/persistence/persistent_contexts.cpp b/src/stlplus/persistence/persistent_contexts.cpp
new file mode 100644 (file)
index 0000000..008fa9f
--- /dev/null
@@ -0,0 +1,434 @@
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+// Author:    Andy Rushton\r
+// Copyright: (c) Southampton University 1999-2004\r
+//              (c) Andy Rushton           2004-2009\r
+// License:   BSD License, see ../docs/license.html\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+#include "persistent_contexts.hpp"\r
+#include "persistent.hpp"\r
+#include <map>\r
+#include <string>\r
+#include <stdio.h>\r
+\r
+namespace stlplus\r
+{\r
+\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // File format version\r
+\r
+  // This relates to the layout of basic types - if I change the file layout of,\r
+  // say, int or vector, then this will change\r
+\r
+  // Early versions of the persistence routines did not have this - they are no longer supported\r
+  // - Change from version 1 to 2: changed the persistent representation of inf\r
+\r
+  unsigned char PersistentVersion = 2;\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // avoid creating dependencies on other libraries\r
+\r
+  static std::string to_string(int number)\r
+  {\r
+    // use sprintf in a very controlled way that cannot overrun\r
+    char* buffer = new char[50];\r
+    sprintf(buffer, "%i", number);\r
+    std::string result = buffer;\r
+    delete buffer;\r
+    return result;\r
+  }\r
+\r
+  static bool little_endian(void)\r
+  {\r
+    // TODO - find a compile-time way of doing this\r
+    int sample = 1;\r
+    char* sample_bytes = (char*)&sample;\r
+    return sample_bytes[0] != 0;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // dump context classes\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  class dump_context_body\r
+  {\r
+  public:\r
+    typedef std::map<const void*,unsigned> magic_map;\r
+    typedef std::map<std::string,dump_context::callback_data> callback_map;\r
+    typedef std::map<std::string,unsigned> interface_map;\r
+\r
+    unsigned m_max_key;\r
+    unsigned char m_version;\r
+    bool m_little_endian;\r
+    std::ostream* m_device;\r
+    magic_map m_pointers;\r
+    callback_map m_callbacks;\r
+    interface_map m_interfaces;\r
+\r
+    dump_context_body(std::ostream& device, unsigned char version) throw(persistent_dump_failed) : \r
+      m_max_key(0), m_version(version), m_little_endian(stlplus::little_endian()), m_device(&device)\r
+      {\r
+        // write the version number as a single byte\r
+        put(version);\r
+        // map a null pointer onto magic number zero\r
+        m_pointers[0] = 0;\r
+        // test whether the version number is supported\r
+        if (m_version != 1 && m_version != 2)\r
+          throw persistent_dump_failed(std::string("wrong version: ") + to_string(m_version));\r
+      }\r
+\r
+    void put(unsigned char data) throw(persistent_dump_failed)\r
+      {\r
+        if (!m_device->put(data))\r
+          throw persistent_dump_failed(std::string("output device error"));\r
+      }\r
+\r
+    const std::ostream& device(void) const\r
+      {\r
+        return *m_device;\r
+      }\r
+\r
+    unsigned char version(void) const\r
+      {\r
+        return m_version;\r
+      }\r
+\r
+    bool little_endian(void) const\r
+      {\r
+        return m_little_endian;\r
+      }\r
+\r
+    std::pair<bool,unsigned> pointer_map(const void* const pointer)\r
+      {\r
+        magic_map::iterator found = m_pointers.find(pointer);\r
+        if (found == m_pointers.end())\r
+        {\r
+          // add a new mapping\r
+          unsigned magic = m_pointers.size();\r
+          m_pointers[pointer] = magic;\r
+          return std::pair<bool,unsigned>(false,magic);\r
+        }\r
+        // return the old mapping\r
+        return std::pair<bool,unsigned>(true,found->second);\r
+      }\r
+\r
+    unsigned register_callback(const std::type_info& info, dump_context::dump_callback callback)\r
+      {\r
+        std::string key = info.name();\r
+        unsigned data = ++m_max_key;\r
+        m_callbacks[key] = std::make_pair(data,callback);\r
+        return data;\r
+      }\r
+\r
+    bool is_callback(const std::type_info& info) const\r
+      {\r
+        return m_callbacks.find(info.name()) != m_callbacks.end();\r
+      }\r
+\r
+    dump_context::callback_data lookup_callback(const std::type_info& info) const throw(persistent_illegal_type)\r
+      {\r
+        std::string key = info.name();\r
+        callback_map::const_iterator found = m_callbacks.find(key);\r
+        if (found == m_callbacks.end())\r
+          throw persistent_illegal_type(key);\r
+        return found->second;\r
+      }\r
+\r
+    unsigned register_interface(const std::type_info& info)\r
+      {\r
+        std::string key = info.name();\r
+        unsigned data = ++m_max_key;\r
+        m_interfaces[key] = data;\r
+        return data;\r
+      }\r
+\r
+    bool is_interface(const std::type_info& info) const\r
+      {\r
+        return m_interfaces.find(info.name()) != m_interfaces.end();\r
+      }\r
+\r
+    unsigned lookup_interface(const std::type_info& info) const throw(persistent_illegal_type)\r
+      {\r
+        std::string key = info.name();\r
+        interface_map::const_iterator found = m_interfaces.find(key);\r
+        if (found == m_interfaces.end())\r
+          throw persistent_illegal_type(key);\r
+        return found->second;\r
+      }\r
+  };\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  dump_context::dump_context(std::ostream& device, unsigned char version) throw(persistent_dump_failed) : m_body(0)\r
+  {\r
+    m_body = new dump_context_body(device,version);\r
+  }\r
+\r
+  dump_context::~dump_context(void)\r
+  {\r
+    delete m_body;\r
+  }\r
+\r
+  void dump_context::put(unsigned char data) throw(persistent_dump_failed)\r
+  {\r
+    m_body->put(data);\r
+  }\r
+\r
+  const std::ostream& dump_context::device(void) const\r
+  {\r
+    return m_body->device();\r
+  }\r
+\r
+  unsigned char dump_context::version(void) const\r
+  {\r
+    return m_body->version();\r
+  }\r
+\r
+  bool dump_context::little_endian(void) const\r
+  {\r
+    return m_body->little_endian();\r
+  }\r
+\r
+  std::pair<bool,unsigned> dump_context::pointer_map(const void* const pointer)\r
+  {\r
+    return m_body->pointer_map(pointer);\r
+  }\r
+\r
+  unsigned dump_context::register_callback(const std::type_info& info, dump_context::dump_callback callback)\r
+  {\r
+    return m_body->register_callback(info,callback);\r
+  }\r
+\r
+  bool dump_context::is_callback(const std::type_info& info) const\r
+  {\r
+    return m_body->is_callback(info);\r
+  }\r
+\r
+  dump_context::callback_data dump_context::lookup_callback(const std::type_info& info) const throw(persistent_illegal_type)\r
+  {\r
+    return m_body->lookup_callback(info);\r
+  }\r
+\r
+  unsigned dump_context::register_interface(const std::type_info& info)\r
+  {\r
+    return m_body->register_interface(info);\r
+  }\r
+\r
+  bool dump_context::is_interface(const std::type_info& info) const\r
+  {\r
+    return m_body->is_interface(info);\r
+  }\r
+\r
+  unsigned dump_context::lookup_interface(const std::type_info& info) const throw(persistent_illegal_type)\r
+  {\r
+    return m_body->lookup_interface(info);\r
+  }\r
+\r
+  void dump_context::register_all(dump_context::installer installer)\r
+  {\r
+    if (installer) installer(*this);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // restore context classes\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  class restore_context_body\r
+  {\r
+  public:\r
+    typedef persistent* persistent_ptr;\r
+    typedef std::map<unsigned,void*> magic_map;\r
+    typedef std::map<unsigned,restore_context::callback_data> callback_map;\r
+    typedef std::map<unsigned,persistent_ptr> interface_map;\r
+\r
+    unsigned m_max_key;\r
+    unsigned char m_version;\r
+    bool m_little_endian;\r
+    std::istream* m_device;\r
+    magic_map m_pointers;\r
+    callback_map m_callbacks;\r
+    interface_map m_interfaces;\r
+\r
+    restore_context_body(std::istream& device) throw(persistent_restore_failed) : \r
+      m_max_key(0), m_little_endian(stlplus::little_endian()), m_device(&device)\r
+      {\r
+        // map a null pointer onto magic number zero\r
+        m_pointers[0] = 0;\r
+        // get the dump version and see if we support it\r
+        m_version = (unsigned char)get();\r
+        if (m_version != 1 && m_version != 2)\r
+          throw persistent_restore_failed(std::string("wrong version: ") + to_string(m_version));\r
+      }\r
+\r
+    ~restore_context_body(void)\r
+      {\r
+        // need to delete all interfaces\r
+        // I used to use smart_ptr_clone for storing them but I want to disconnect as many dependencies as possible\r
+        for (unsigned i = 0; i < m_interfaces.size(); i++)\r
+          delete m_interfaces[i];\r
+      }\r
+\r
+    const std::istream& device(void) const\r
+      {\r
+        return *m_device;\r
+      }\r
+\r
+    unsigned char version(void) const\r
+      {\r
+        return m_version;\r
+      }\r
+\r
+    bool little_endian(void) const\r
+      {\r
+        return m_little_endian;\r
+      }\r
+\r
+    int get(void) throw(persistent_restore_failed)\r
+      {\r
+        int result = m_device->get();\r
+        if (!m_device->good())\r
+          throw persistent_restore_failed(std::string("device error or premature end of file"));\r
+        return result;\r
+      }\r
+\r
+    std::pair<bool,void*> pointer_map(unsigned magic)\r
+      {\r
+        magic_map::iterator found = m_pointers.find(magic);\r
+        if (found == m_pointers.end())\r
+        {\r
+          // this magic number has never been seen before\r
+          return std::pair<bool,void*>(false,0);\r
+        }\r
+        return std::pair<bool,void*>(true,found->second);\r
+      }\r
+\r
+    void pointer_add(unsigned magic, void* new_pointer)\r
+      {\r
+        m_pointers[magic] = new_pointer;\r
+      }\r
+\r
+    unsigned register_callback(restore_context::create_callback create, restore_context::restore_callback restore)\r
+      {\r
+        unsigned key = ++m_max_key;\r
+        m_callbacks[key] = std::make_pair(create,restore);\r
+        return key;\r
+      }\r
+\r
+    bool is_callback(unsigned key) const\r
+      {\r
+        return m_callbacks.find(key) != m_callbacks.end();\r
+      }\r
+\r
+    restore_context::callback_data lookup_callback(unsigned key) const throw(persistent_illegal_type)\r
+      {\r
+        callback_map::const_iterator found = m_callbacks.find(key);\r
+        if (found == m_callbacks.end())\r
+          throw persistent_illegal_type(key);\r
+        return found->second;\r
+      }\r
+\r
+    unsigned register_interface(persistent* sample)\r
+      {\r
+        unsigned key = ++m_max_key;\r
+        m_interfaces[key] = sample;\r
+        return key;\r
+      }\r
+\r
+    bool is_interface(unsigned key) const\r
+      {\r
+        return m_interfaces.find(key) != m_interfaces.end();\r
+      }\r
+\r
+    persistent* lookup_interface(unsigned key) const throw(persistent_illegal_type)\r
+      {\r
+        interface_map::const_iterator found = m_interfaces.find(key);\r
+        if (found == m_interfaces.end())\r
+          throw persistent_illegal_type(key);\r
+        return found->second;\r
+      }\r
+  };\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  restore_context::restore_context(std::istream& device) throw(persistent_restore_failed) : \r
+    m_body(0)\r
+  {\r
+    m_body = new restore_context_body(device);\r
+  }\r
+\r
+  restore_context::~restore_context(void)\r
+  {\r
+    delete m_body;\r
+  }\r
+\r
+  const std::istream& restore_context::device(void) const\r
+  {\r
+    return m_body->device();\r
+  }\r
+\r
+  unsigned char restore_context::version(void) const\r
+  {\r
+    return m_body->version();\r
+  }\r
+\r
+  bool restore_context::little_endian(void) const\r
+  {\r
+    return m_body->little_endian();\r
+  }\r
+\r
+  int restore_context::get(void) throw(persistent_restore_failed)\r
+  {\r
+    return m_body->get();\r
+  }\r
+\r
+  std::pair<bool,void*> restore_context::pointer_map(unsigned magic)\r
+  {\r
+    return m_body->pointer_map(magic);\r
+  }\r
+\r
+  void restore_context::pointer_add(unsigned magic, void* new_pointer)\r
+  {\r
+    m_body->pointer_add(magic,new_pointer);\r
+  }\r
+\r
+  unsigned restore_context::register_callback(restore_context::create_callback create, restore_context::restore_callback restore)\r
+  {\r
+    return m_body->register_callback(create,restore);\r
+  }\r
+\r
+  bool restore_context::is_callback(unsigned key) const\r
+  {\r
+    return m_body->is_callback(key);\r
+  }\r
+\r
+  restore_context::callback_data restore_context::lookup_callback(unsigned key) const throw(persistent_illegal_type)\r
+  {\r
+    return m_body->lookup_callback(key);\r
+  }\r
+\r
+  unsigned restore_context::register_interface(persistent* sample)\r
+  {\r
+    return m_body->register_interface(sample);\r
+  }\r
+\r
+  bool restore_context::is_interface(unsigned key) const\r
+  {\r
+    return m_body->is_interface(key);\r
+  }\r
+\r
+  persistent* restore_context::lookup_interface(unsigned key) const throw(persistent_illegal_type)\r
+  {\r
+    return m_body->lookup_interface(key);\r
+  }\r
+\r
+  void restore_context::register_all(restore_context::installer installer)\r
+  {\r
+    if (installer) installer(*this);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+} // end namespace stlplus\r
+\r
This page took 0.03175 seconds and 4 git commands to generate.