diff options
| author | Rusty Wagner <rusty@vector35.com> | 2015-04-26 21:38:29 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2015-04-26 21:38:53 -0400 |
| commit | f576bc88bdecba3d634482777142a2d7c84600c6 (patch) | |
| tree | 426340049d84833fa9536be051f34093bd13a3d7 | |
| parent | a641c5266ad2a55af2bdd277a2b889ced4eb7235 (diff) | |
Add serialization API for undo actions to prepare for storing in database
| -rw-r--r-- | api.pro | 3 | ||||
| -rw-r--r-- | binaryninjaapi.h | 40 | ||||
| -rw-r--r-- | binaryview.cpp | 6 | ||||
| -rw-r--r-- | filemetadata.cpp | 95 |
4 files changed, 121 insertions, 23 deletions
@@ -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); |
