]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/persist.h
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / include / wx / persist.h
index 23cf0691db510e693cd6a92e6b218094c38be182..18bcdc2d793077e9e9eb02d1afaf14565901108b 100644 (file)
-///////////////////////////////////////////////////////////////////////////////\r
-// Name:        wx/persist.h\r
-// Purpose:     common classes for persistence support\r
-// Author:      Vadim Zeitlin\r
-// Created:     2009-01-18\r
-// RCS-ID:      $Id: wxhead.h,v 1.10 2008-04-15 23:34:19 zeitlin Exp $\r
-// Copyright:   (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>\r
-// Licence:     wxWindows licence\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifndef _WX_PERSIST_H_\r
-#define _WX_PERSIST_H_\r
-\r
-#include "wx/string.h"\r
-#include "wx/hashmap.h"\r
-#include "wx/confbase.h"\r
-\r
-class wxPersistentObject;\r
-\r
-WX_DECLARE_VOIDPTR_HASH_MAP(wxPersistentObject *, wxPersistentObjectsMap);\r
-\r
-// ----------------------------------------------------------------------------\r
-// global functions\r
-// ----------------------------------------------------------------------------\r
-\r
-/*\r
-   We do _not_ declare this function as doing this would force us to specialize\r
-   it for the user classes deriving from the standard persistent classes.\r
-   However we do define overloads of wxCreatePersistentObject() for all the wx\r
-   classes which means that template wxPersistentObject::Restore() picks up the\r
-   right overload to use provided that the header defining the correct overload\r
-   is included before calling it. And a compilation error happens if this is\r
-   not done.\r
-\r
-template <class T>\r
-wxPersistentObject *wxCreatePersistentObject(T *obj);\r
-\r
- */\r
-\r
-// ----------------------------------------------------------------------------\r
-// wxPersistenceManager: global aspects of persistent windows\r
-// ----------------------------------------------------------------------------\r
-\r
-class WXDLLIMPEXP_CORE wxPersistenceManager\r
-{\r
-public:\r
-    // accessor to the unique persistence manager object\r
-    static wxPersistenceManager& Get();\r
-\r
-\r
-    // globally disable restoring or saving the persistent properties (both are\r
-    // enabled by default)\r
-    void DisableSaving() { m_doSave = false; }\r
-    void DisableRestoring() { m_doRestore = false; }\r
-\r
-\r
-    // register an object with the manager: when using the first overload,\r
-    // wxCreatePersistentObject() must be specialized for this object class;\r
-    // with the second one the persistent adapter is created by the caller\r
-    //\r
-    // the object shouldn't be already registered with us\r
-    template <class T>\r
-    wxPersistentObject *Register(T *obj)\r
-    {\r
-        return Register(obj, wxCreatePersistentObject(obj));\r
-    }\r
-\r
-    wxPersistentObject *Register(void *obj, wxPersistentObject *po);\r
-\r
-    // check if the object is registered and return the associated\r
-    // wxPersistentObject if it is or NULL otherwise\r
-    wxPersistentObject *Find(void *obj) const;\r
-\r
-    // unregister the object, this is called by wxPersistentObject itself so\r
-    // there is usually no need to do it explicitly\r
-    //\r
-    // deletes the associated wxPersistentObject\r
-    void Unregister(void *obj);\r
-\r
-    \r
-    // save/restore the state of an object\r
-    //\r
-    // these methods do nothing if DisableSaving/Restoring() was called\r
-    //\r
-    // Restore() returns true if the object state was really restored\r
-    void Save(void *obj);\r
-    bool Restore(void *obj);\r
-\r
-    // combines both Save() and Unregister() calls\r
-    void SaveAndUnregister(void *obj)\r
-    {\r
-        Save(obj);\r
-        Unregister(obj);\r
-    }\r
-\r
-    // combines both Register() and Restore() calls\r
-    template <class T>\r
-    bool RegisterAndRestore(T *obj)\r
-    {\r
-        return Register(obj) && Restore(obj);\r
-    }\r
-\r
-    bool RegisterAndRestore(void *obj, wxPersistentObject *po)\r
-    {\r
-        return Register(obj, po) && Restore(obj);\r
-    }\r
-\r
-\r
-    // methods used by the persistent objects to save and restore the data\r
-    //\r
-    // currently these methods simply use wxConfig::Get()\r
-    //\r
-    // TODO: make this customizable by allowing\r
-    //          (a) specifying custom wxConfig object to use\r
-    //          (b) allowing to use something else entirely\r
-    template <typename T>\r
-    bool\r
-    SaveValue(const wxPersistentObject& who, const wxString& name, T value)\r
-    {\r
-        wxConfigBase * const conf = GetConfig();\r
-        if ( !conf )\r
-            return false;\r
-\r
-        return conf->Write(GetKey(who, name), value);\r
-    }\r
-\r
-    template <typename T>\r
-    bool\r
-    RestoreValue(const wxPersistentObject& who, const wxString& name, T *value)\r
-    {\r
-        wxConfigBase * const conf = GetConfig();\r
-        if ( !conf )\r
-            return false;\r
-\r
-        return conf->Read(GetKey(who, name), value);\r
-    }\r
-\r
-private:\r
-    // ctor is private, use Get()\r
-    wxPersistenceManager()\r
-    {\r
-        m_doSave =\r
-        m_doRestore = true;\r
-    }\r
-\r
-    // helpers of Save/Restore(), will be customized later\r
-    wxConfigBase *GetConfig() const { return wxConfigBase::Get(); }\r
-    wxString GetKey(const wxPersistentObject& who, const wxString& name) const;\r
-\r
-\r
-    // map with the registered objects as keys and associated\r
-    // wxPersistentObjects as values\r
-    wxPersistentObjectsMap m_persistentObjects;\r
-\r
-    // true if we should restore/save the settings (it doesn't make much sense\r
-    // to use this class when both of them are false but setting one of them to\r
-    // false may make sense in some situations)\r
-    bool m_doSave,\r
-         m_doRestore;\r
-\r
-    DECLARE_NO_COPY_CLASS(wxPersistenceManager);\r
-};\r
-\r
-// ----------------------------------------------------------------------------\r
-// wxPersistentObject: ABC for anything persistent\r
-// ----------------------------------------------------------------------------\r
-\r
-class wxPersistentObject\r
-{\r
-public:\r
-    // ctor associates us with the object whose options we save/restore\r
-    wxPersistentObject(void *obj) : m_obj(obj) { }\r
-\r
-    // trivial but virtual dtor\r
-    virtual ~wxPersistentObject() { }\r
-\r
-\r
-    // methods used by wxPersistenceManager\r
-    // ------------------------------------\r
-\r
-    // save/restore the corresponding objects settings\r
-    //\r
-    // these methods shouldn't be used directly as they don't respect the\r
-    // global wxPersistenceManager::DisableSaving/Restoring() settings, use\r
-    // wxPersistenceManager methods with the same name instead\r
-    virtual void Save() const = 0;\r
-    virtual bool Restore() = 0;\r
-\r
-\r
-    // get the kind of the objects we correspond to, e.g. "Frame"\r
-    virtual wxString GetKind() const = 0;\r
-\r
-    // get the name of the object we correspond to, e.g. "Main"\r
-    virtual wxString GetName() const = 0;\r
-\r
-\r
-    // return the associated object\r
-    void *GetObject() const { return m_obj; }\r
-\r
-protected:\r
-    // wrappers for wxPersistenceManager methods which don't require passing\r
-    // "this" as the first parameter all the time\r
-    template <typename T>\r
-    bool SaveValue(const wxString& name, T value) const\r
-    {\r
-        return wxPersistenceManager::Get().SaveValue(*this, name, value);\r
-    }\r
-\r
-    template <typename T>\r
-    bool RestoreValue(const wxString& name, T *value)\r
-    {\r
-        return wxPersistenceManager::Get().RestoreValue(*this, name, value);\r
-    }\r
-\r
-private:\r
-    void * const m_obj;\r
-\r
-    DECLARE_NO_COPY_CLASS(wxPersistentObject)\r
-};\r
-\r
-#endif // _WX_PERSIST_H_\r
-\r
+///////////////////////////////////////////////////////////////////////////////
+// Name:        wx/persist.h
+// Purpose:     common classes for persistence support
+// Author:      Vadim Zeitlin
+// Created:     2009-01-18
+// RCS-ID:      $Id$
+// Copyright:   (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PERSIST_H_
+#define _WX_PERSIST_H_
+
+#include "wx/string.h"
+#include "wx/hashmap.h"
+#include "wx/confbase.h"
+
+class wxPersistentObject;
+
+WX_DECLARE_VOIDPTR_HASH_MAP(wxPersistentObject *, wxPersistentObjectsMap);
+
+// ----------------------------------------------------------------------------
+// global functions
+// ----------------------------------------------------------------------------
+
+/*
+   We do _not_ declare this function as doing this would force us to specialize
+   it for the user classes deriving from the standard persistent classes.
+   However we do define overloads of wxCreatePersistentObject() for all the wx
+   classes which means that template wxPersistentObject::Restore() picks up the
+   right overload to use provided that the header defining the correct overload
+   is included before calling it. And a compilation error happens if this is
+   not done.
+
+template <class T>
+wxPersistentObject *wxCreatePersistentObject(T *obj);
+
+ */
+
+// ----------------------------------------------------------------------------
+// wxPersistenceManager: global aspects of persistent windows
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxPersistenceManager
+{
+public:
+    // Call this method to specify a non-default persistence manager to use.
+    // This function should usually be called very early to affect creation of
+    // all persistent controls and the object passed to it must have a lifetime
+    // long enough to be still alive when the persistent controls are destroyed
+    // and need it to save their state so typically this would be a global or a
+    // wxApp member.
+    static void Set(wxPersistenceManager& manager);
+
+    // accessor to the unique persistence manager object
+    static wxPersistenceManager& Get();
+
+    // trivial but virtual dtor
+    //
+    // FIXME-VC6: this only needs to be public because of VC6 bug
+    virtual ~wxPersistenceManager();
+
+
+    // globally disable restoring or saving the persistent properties (both are
+    // enabled by default)
+    void DisableSaving() { m_doSave = false; }
+    void DisableRestoring() { m_doRestore = false; }
+
+
+    // register an object with the manager: when using the first overload,
+    // wxCreatePersistentObject() must be specialized for this object class;
+    // with the second one the persistent adapter is created by the caller
+    //
+    // the object shouldn't be already registered with us
+    template <class T>
+    wxPersistentObject *Register(T *obj)
+    {
+        return Register(obj, wxCreatePersistentObject(obj));
+    }
+
+    wxPersistentObject *Register(void *obj, wxPersistentObject *po);
+
+    // check if the object is registered and return the associated
+    // wxPersistentObject if it is or NULL otherwise
+    wxPersistentObject *Find(void *obj) const;
+
+    // unregister the object, this is called by wxPersistentObject itself so
+    // there is usually no need to do it explicitly
+    //
+    // deletes the associated wxPersistentObject
+    void Unregister(void *obj);
+
+
+    // save/restore the state of an object
+    //
+    // these methods do nothing if DisableSaving/Restoring() was called
+    //
+    // Restore() returns true if the object state was really restored
+    void Save(void *obj);
+    bool Restore(void *obj);
+
+    // combines both Save() and Unregister() calls
+    void SaveAndUnregister(void *obj)
+    {
+        Save(obj);
+        Unregister(obj);
+    }
+
+    // combines both Register() and Restore() calls
+    template <class T>
+    bool RegisterAndRestore(T *obj)
+    {
+        return Register(obj) && Restore(obj);
+    }
+
+    bool RegisterAndRestore(void *obj, wxPersistentObject *po)
+    {
+        return Register(obj, po) && Restore(obj);
+    }
+
+
+    // methods used by the persistent objects to save and restore the data
+    //
+    // currently these methods simply use wxConfig::Get() but they may be
+    // overridden in the derived class (once we allow creating custom
+    // persistent managers)
+#define wxPERSIST_DECLARE_SAVE_RESTORE_FOR(Type)                              \
+    virtual bool SaveValue(const wxPersistentObject& who,                     \
+                           const wxString& name,                              \
+                           Type value);                                       \
+                                                                              \
+    virtual bool                                                              \
+    RestoreValue(const wxPersistentObject& who,                               \
+                 const wxString& name,                                        \
+                 Type *value)
+
+    wxPERSIST_DECLARE_SAVE_RESTORE_FOR(bool);
+    wxPERSIST_DECLARE_SAVE_RESTORE_FOR(int);
+    wxPERSIST_DECLARE_SAVE_RESTORE_FOR(long);
+    wxPERSIST_DECLARE_SAVE_RESTORE_FOR(wxString);
+
+#undef wxPERSIST_DECLARE_SAVE_RESTORE_FOR
+
+protected:
+    // ctor is private, use Get()
+    wxPersistenceManager()
+    {
+        m_doSave =
+        m_doRestore = true;
+    }
+
+
+    // Return the config object to use, by default just the global one but a
+    // different one could be used by the derived class if needed.
+    virtual wxConfigBase *GetConfig() const { return wxConfigBase::Get(); }
+
+    // Return the path to use for saving the setting with the given name for
+    // the specified object (notice that the name is the name of the setting,
+    // not the name of the object itself which can be retrieved with GetName()).
+    virtual wxString GetKey(const wxPersistentObject& who,
+                            const wxString& name) const;
+
+
+private:
+    // map with the registered objects as keys and associated
+    // wxPersistentObjects as values
+    wxPersistentObjectsMap m_persistentObjects;
+
+    // true if we should restore/save the settings (it doesn't make much sense
+    // to use this class when both of them are false but setting one of them to
+    // false may make sense in some situations)
+    bool m_doSave,
+         m_doRestore;
+
+    wxDECLARE_NO_COPY_CLASS(wxPersistenceManager);
+};
+
+// ----------------------------------------------------------------------------
+// wxPersistentObject: ABC for anything persistent
+// ----------------------------------------------------------------------------
+
+class wxPersistentObject
+{
+public:
+    // ctor associates us with the object whose options we save/restore
+    wxPersistentObject(void *obj) : m_obj(obj) { }
+
+    // trivial but virtual dtor
+    virtual ~wxPersistentObject() { }
+
+
+    // methods used by wxPersistenceManager
+    // ------------------------------------
+
+    // save/restore the corresponding objects settings
+    //
+    // these methods shouldn't be used directly as they don't respect the
+    // global wxPersistenceManager::DisableSaving/Restoring() settings, use
+    // wxPersistenceManager methods with the same name instead
+    virtual void Save() const = 0;
+    virtual bool Restore() = 0;
+
+
+    // get the kind of the objects we correspond to, e.g. "Frame"
+    virtual wxString GetKind() const = 0;
+
+    // get the name of the object we correspond to, e.g. "Main"
+    virtual wxString GetName() const = 0;
+
+
+    // return the associated object
+    void *GetObject() const { return m_obj; }
+
+protected:
+    // wrappers for wxPersistenceManager methods which don't require passing
+    // "this" as the first parameter all the time
+    template <typename T>
+    bool SaveValue(const wxString& name, T value) const
+    {
+        return wxPersistenceManager::Get().SaveValue(*this, name, value);
+    }
+
+    template <typename T>
+    bool RestoreValue(const wxString& name, T *value)
+    {
+        return wxPersistenceManager::Get().RestoreValue(*this, name, value);
+    }
+
+private:
+    void * const m_obj;
+
+    wxDECLARE_NO_COPY_CLASS(wxPersistentObject);
+};
+
+// FIXME-VC6: VC6 has troubles with template methods of DLL-exported classes,
+//            apparently it believes they should be defined in the DLL (which
+//            is, of course, impossible as the DLL doesn't know for which types
+//            will they be instantiated) instead of compiling them when
+//            building the main application itself. Because of this problem
+//            (which only arises in debug build!) we can't use the usual
+//            RegisterAndRestore(obj) with it and need to explicitly create the
+//            persistence adapter. To hide this ugliness we define a global
+//            function which does it for us.
+template <typename T>
+inline bool wxPersistentRegisterAndRestore(T *obj)
+{
+    wxPersistentObject * const pers = wxCreatePersistentObject(obj);
+
+    return wxPersistenceManager::Get().RegisterAndRestore(obj, pers);
+
+}
+
+// A helper function which also sets the name for the (wxWindow-derived) object
+// before registering and restoring it.
+template <typename T>
+inline bool wxPersistentRegisterAndRestore(T *obj, const wxString& name)
+{
+    obj->SetName(name);
+
+    return wxPersistentRegisterAndRestore(obj);
+}
+
+#endif // _WX_PERSIST_H_
+