summaryrefslogtreecommitdiff
path: root/library/DataDefs.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2011-12-24 14:51:58 +0400
committerAlexander Gavrilov2011-12-24 14:51:58 +0400
commit79ac2a781a3bfd3395a5785098a16403c1a9d3ce (patch)
tree91b5942ba1a17f81554f6ae89d95b81d2aeb2ee5 /library/DataDefs.cpp
parent0b5a470a3894b1cbaaf3970e4416bd35371493d0 (diff)
downloaddfhack-79ac2a781a3bfd3395a5785098a16403c1a9d3ce.tar.gz
dfhack-79ac2a781a3bfd3395a5785098a16403c1a9d3ce.tar.bz2
dfhack-79ac2a781a3bfd3395a5785098a16403c1a9d3ce.tar.xz
Add infrastructure necessary to use the generated headers.
As a usage example, allow toggling water level display and idlers, and implement a ui tweak for easily copying stockpiles. Also disable df2mc by default - default options shouldn't require anything not in the base package.
Diffstat (limited to 'library/DataDefs.cpp')
-rw-r--r--library/DataDefs.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp
new file mode 100644
index 00000000..2de8c156
--- /dev/null
+++ b/library/DataDefs.cpp
@@ -0,0 +1,136 @@
+/*
+https://github.com/peterix/dfhack
+Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "Internal.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "dfhack/Process.h"
+#include "dfhack/Core.h"
+#include "dfhack/DataDefs.h"
+#include "dfhack/VersionInfo.h"
+#include "tinythread.h"
+
+using namespace DFHack;
+
+/* The order of global object constructor calls is
+ * undefined between compilation units. Therefore,
+ * this list has to be plain data, so that it gets
+ * initialized by the loader in the initial mmap.
+ */
+virtual_identity *virtual_identity::list = NULL;
+
+virtual_identity::virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent)
+ : dfhack_name(dfhack_name), original_name(original_name), parent(parent),
+ prev(NULL), vtable_ptr(NULL), has_children(true)
+{
+ // Link into the static list. Nothing else can be safely done at this point.
+ next = list; list = this;
+}
+
+/* Vtable to identity lookup. */
+static tthread::mutex *known_mutex = NULL;
+std::map<void*, virtual_identity*> virtual_identity::known;
+
+virtual_identity *virtual_identity::get(virtual_class *instance_ptr)
+{
+ if (!instance_ptr) return NULL;
+
+ // Actually, a reader/writer lock would be sufficient,
+ // since the table is only written once per class.
+ tthread::lock_guard<tthread::mutex> lock(*known_mutex);
+
+ void *vtable = get_vtable(instance_ptr);
+ std::map<void*, virtual_identity*>::iterator it = known.find(vtable);
+
+ if (it != known.end())
+ return it->second;
+
+ // If using a reader/writer lock, re-grab as write here, and recheck
+ Core &core = Core::getInstance();
+ std::string name = core.p->doReadClassName(vtable);
+
+ virtual_identity *actual = NULL;
+
+ for (virtual_identity *p = list; p; p = p->next) {
+ if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue;
+ known[vtable] = p;
+ p->vtable_ptr = vtable;
+ return p;
+ }
+
+ known[vtable] = NULL;
+ return NULL;
+}
+
+bool virtual_identity::check_instance(virtual_class *instance_ptr, bool allow_subclasses)
+{
+ virtual_identity *actual = get(instance_ptr);
+
+ if (actual == this) return true;
+ if (!allow_subclasses || !actual) return false;
+
+ do {
+ actual = actual->parent;
+ if (actual == this) return true;
+ } while (actual);
+
+ return false;
+}
+
+void virtual_identity::Init()
+{
+ if (!known_mutex)
+ known_mutex = new tthread::mutex();
+
+ // This cannot be done in the constructors, because
+ // they are called in an undefined order.
+ for (virtual_identity *p = list; p; p = p->next) {
+ p->has_children = false;
+ p->children.clear();
+ }
+ for (virtual_identity *p = list; p; p = p->next) {
+ if (p->parent) {
+ p->parent->children.push_back(p);
+ p->parent->has_children = true;
+ }
+ }
+}
+
+#define GLOBAL(name,tname) \
+ df::tname *df::global::name = NULL;
+DF_KNOWN_GLOBALS
+#undef GLOBAL
+
+void DFHack::InitDataDefGlobals(Core *core) {
+ OffsetGroup *global_table = core->vinfo->getGroup("global");
+ uint32_t tmp;
+
+#define GLOBAL(name,tname) \
+ if (global_table->getSafeAddress(#name,tmp)) df::global::name = (df::tname*)tmp;
+DF_KNOWN_GLOBALS
+#undef GLOBAL
+}