summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2015-04-26 21:38:29 -0400
committerRusty Wagner <rusty@vector35.com>2015-04-26 21:38:53 -0400
commitf576bc88bdecba3d634482777142a2d7c84600c6 (patch)
tree426340049d84833fa9536be051f34093bd13a3d7
parenta641c5266ad2a55af2bdd277a2b889ced4eb7235 (diff)
Add serialization API for undo actions to prepare for storing in database
-rw-r--r--api.pro3
-rw-r--r--binaryninjaapi.h40
-rw-r--r--binaryview.cpp6
-rw-r--r--filemetadata.cpp95
4 files changed, 121 insertions, 23 deletions
diff --git a/api.pro b/api.pro
index 3cf7dfa7..57eb935c 100644
--- a/api.pro
+++ b/api.pro
@@ -26,7 +26,8 @@ SOURCES += \
functiongraph.cpp \
functiongraphblock.cpp \
log.cpp \
- tempfile.cpp
+ tempfile.cpp \
+ ../core/json/jsoncpp.cpp
HEADERS += binaryninjaapi.h
unix {
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index c29804b6..0eaf38b7 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -10,6 +10,7 @@
#include <exception>
#include <functional>
#include "binaryninjacore.h"
+#include "json/json.h"
#ifdef _MSC_VER
#define NOEXCEPT
@@ -226,19 +227,45 @@ namespace BinaryNinja
virtual bool Navigate(const std::string& view, uint64_t offset) = 0;
};
+ class BinaryView;
+
class UndoAction
{
private:
- static void UndoCallback(void* ctxt);
- static void RedoCallback(void* ctxt);
+ std::string m_name;
+
+ static void UndoCallback(void* ctxt, BNBinaryView* data);
+ static void RedoCallback(void* ctxt, BNBinaryView* data);
+ static char* SerializeCallback(void* ctxt);
public:
+ UndoAction(const std::string& name);
virtual ~UndoAction() {}
- void Add(BNFileMetadata* file);
+ const std::string& GetName() const { return m_name; }
+ BNUndoAction GetCallbacks();
+
+ void Add(BNBinaryView* view);
- virtual void Undo() = 0;
- virtual void Redo() = 0;
+ virtual void Undo(BinaryView* data) = 0;
+ virtual void Redo(BinaryView* data) = 0;
+ virtual Json::Value Serialize() = 0;
+ };
+
+ class UndoActionType
+ {
+ protected:
+ std::string m_nameForRegister;
+
+ static bool DeserializeCallback(void* ctxt, const char* data, BNUndoAction* result);
+
+ public:
+ UndoActionType(const std::string& name);
+ virtual ~UndoActionType() {}
+
+ static void Register(UndoActionType* type);
+
+ virtual UndoAction* Deserialize(const Json::Value& data) = 0;
};
class FileMetadata: public RefCountObject
@@ -263,7 +290,6 @@ namespace BinaryNinja
void MarkFileSaved();
void BeginUndoActions();
- void AddUndoAction(UndoAction* action);
void CommitUndoActions();
bool Undo();
@@ -374,7 +400,7 @@ namespace BinaryNinja
BNBinaryView* m_view;
Ref<FileMetadata> m_file;
- BinaryView(FileMetadata* file);
+ BinaryView(const std::string& typeName, FileMetadata* file);
virtual size_t PerformRead(void* dest, uint64_t offset, size_t len) { (void)dest; (void)offset; (void)len; return 0; }
virtual size_t PerformWrite(uint64_t offset, const void* data, size_t len) { (void)offset; (void)data; (void)len; return 0; }
diff --git a/binaryview.cpp b/binaryview.cpp
index 02f0501b..4d5c839a 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -130,7 +130,7 @@ uint64_t Symbol::GetAddress() const
}
-BinaryView::BinaryView(FileMetadata* file)
+BinaryView::BinaryView(const std::string& typeName, FileMetadata* file)
{
BNCustomBinaryView view;
view.context = this;
@@ -148,7 +148,7 @@ BinaryView::BinaryView(FileMetadata* file)
view.save = SaveCallback;
m_file = file;
- m_view = BNCreateCustomBinaryView(m_file->GetFileObject(), &view);
+ m_view = BNCreateCustomBinaryView(typeName.c_str(), m_file->GetFileObject(), &view);
}
@@ -316,7 +316,7 @@ void BinaryView::BeginUndoActions()
void BinaryView::AddUndoAction(UndoAction* action)
{
- m_file->AddUndoAction(action);
+ action->Add(m_view);
}
diff --git a/filemetadata.cpp b/filemetadata.cpp
index 0824d234..5775852a 100644
--- a/filemetadata.cpp
+++ b/filemetadata.cpp
@@ -1,6 +1,7 @@
#include "binaryninjaapi.h"
using namespace BinaryNinja;
+using namespace Json;
using namespace std;
@@ -35,23 +36,99 @@ NavigationHandler::NavigationHandler()
}
-void UndoAction::UndoCallback(void* ctxt)
+void UndoAction::UndoCallback(void* ctxt, BNBinaryView* data)
{
UndoAction* action = (UndoAction*)ctxt;
- action->Undo();
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ action->Undo(view);
}
-void UndoAction::RedoCallback(void* ctxt)
+void UndoAction::RedoCallback(void* ctxt, BNBinaryView* data)
{
UndoAction* action = (UndoAction*)ctxt;
- action->Redo();
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ action->Redo(view);
}
-void UndoAction::Add(BNFileMetadata* file)
+char* UndoAction::SerializeCallback(void* ctxt)
{
- BNAddUndoAction(file, this, UndoCallback, RedoCallback);
+ try
+ {
+ UndoAction* action = (UndoAction*)ctxt;
+ Value data = action->Serialize();
+ FastWriter writer;
+ string json = writer.write(data);
+ return BNAllocString(json.c_str());
+ }
+ catch (exception& e)
+ {
+ LogError("Undo action failed to serialize: %s", e.what());
+ return nullptr;
+ }
+}
+
+
+UndoAction::UndoAction(const string& name): m_name(name)
+{
+}
+
+
+BNUndoAction UndoAction::GetCallbacks()
+{
+ BNUndoAction action;
+ action.context = this;
+ action.undo = UndoCallback;
+ action.redo = RedoCallback;
+ action.serialize = SerializeCallback;
+ return action;
+}
+
+
+void UndoAction::Add(BNBinaryView* view)
+{
+ BNUndoAction action = GetCallbacks();
+ BNAddUndoAction(view, GetName().c_str(), &action);
+}
+
+
+bool UndoActionType::DeserializeCallback(void* ctxt, const char* data, BNUndoAction* result)
+{
+ try
+ {
+ UndoActionType* type = (UndoActionType*)ctxt;
+ Reader reader;
+ Value val;
+ if (!reader.parse(data, val, false))
+ {
+ LogError("Invalid JSON while deserializing undo action");
+ return false;
+ }
+
+ UndoAction* action = type->Deserialize(val);
+ if (!action)
+ return false;
+
+ *result = action->GetCallbacks();
+ return true;
+ }
+ catch (exception& e)
+ {
+ LogError("Error while deserializing undo action: %s", e.what());
+ return false;
+ }
+}
+
+
+UndoActionType::UndoActionType(const string& name): m_nameForRegister(name)
+{
+}
+
+
+void UndoActionType::Register(UndoActionType* type)
+{
+ BNRegisterUndoActionType(type->m_nameForRegister.c_str(), type, DeserializeCallback);
}
@@ -125,12 +202,6 @@ void FileMetadata::BeginUndoActions()
}
-void FileMetadata::AddUndoAction(UndoAction* action)
-{
- action->Add(m_file);
-}
-
-
void FileMetadata::CommitUndoActions()
{
BNCommitUndoActions(m_file);