Skeleton type metadata for future use in lua bindings.

develop
Alexander Gavrilov 2012-03-19 16:59:11 +04:00
parent bfb226b92e
commit 296d3a0af3
7 changed files with 502 additions and 89 deletions

@ -57,6 +57,7 @@ ColorText.cpp
DataDefs.cpp
DataStatics.cpp
DataStaticsCtor.cpp
DataStaticsFields.cpp
MiscUtils.cpp
PluginManager.cpp
TileTypes.cpp
@ -195,6 +196,14 @@ ADD_CUSTOM_COMMAND(
ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/df/static.inc)
IF(UNIX)
# Don't produce debug info for generated stubs
SET_SOURCE_FILES_PROPERTIES(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp
PROPERTIES COMPILE_FLAGS "-g0")
ELSE(WIN32)
ENDIF()
# Compilation
ADD_DEFINITIONS(-DBUILD_DFHACK_LIB)

@ -44,18 +44,107 @@ using namespace DFHack;
* 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;
compound_identity *compound_identity::list = NULL;
std::vector<compound_identity*> compound_identity::top_scope;
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)
compound_identity::compound_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name)
: constructed_identity(size, alloc), scope_parent(scope_parent), dfhack_name(dfhack_name)
{
// Link into the static list. Nothing else can be safely done at this point.
next = list; list = this;
next = list; list = this;
}
void compound_identity::doInit(Core *)
{
if (scope_parent)
scope_parent->scope_children.push_back(this);
else
top_scope.push_back(this);
}
/* Vtable to identity lookup. */
static tthread::mutex *known_mutex = NULL;
void compound_identity::Init(Core *core)
{
if (!known_mutex)
known_mutex = new tthread::mutex();
// This cannot be done in the constructors, because
// they are called in an undefined order.
for (compound_identity *p = list; p; p = p->next)
p->doInit(core);
//FIXME: ... nuked. the group was empty...
/*
// Read pre-filled vtable ptrs
OffsetGroup *ptr_table = core->vinfo->getGroup("vtable");
for (virtual_identity *p = list; p; p = p->next) {
void * tmp;
if (ptr_table->getSafeAddress(p->getName(),tmp))
p->vtable_ptr = tmp;
}
*/
}
bitfield_identity::bitfield_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
int num_bits, const bitfield_item_info *bits)
: compound_identity(size, alloc, scope_parent, dfhack_name), bits(bits), num_bits(num_bits)
{
}
enum_identity::enum_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
int64_t first_item_value, int64_t last_item_value,
const char *const *keys)
: compound_identity(size, alloc, scope_parent, dfhack_name),
first_item_value(first_item_value), last_item_value(last_item_value), keys(keys)
{
}
struct_identity::struct_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
struct_identity *parent, const struct_field_info *fields)
: compound_identity(size, alloc, scope_parent, dfhack_name), parent(parent), has_children(false)
{
}
void struct_identity::doInit(Core *core)
{
compound_identity::doInit(core);
if (parent) {
parent->children.push_back(this);
parent->has_children = true;
}
}
bool struct_identity::is_subclass(struct_identity *actual)
{
for (; actual; actual = actual->getParent())
if (actual == this) return true;
return false;
}
virtual_identity::virtual_identity(size_t size, TAllocateFn alloc,
const char *dfhack_name, const char *original_name,
virtual_identity *parent, const struct_field_info *fields)
: struct_identity(size, alloc, NULL, dfhack_name, parent, fields), original_name(original_name),
vtable_ptr(NULL)
{
}
static std::map<std::string, virtual_identity*> name_lookup;
void virtual_identity::doInit(Core *core)
{
struct_identity::doInit(core);
name_lookup[getOriginalName()] = this;
}
/* Vtable to identity lookup. */
std::map<void*, virtual_identity*> virtual_identity::known;
virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
@ -78,8 +167,9 @@ virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
virtual_identity *actual = NULL;
for (virtual_identity *p = list; p; p = p->next) {
if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue;
auto name_it = name_lookup.find(name);
if (name_it != name_lookup.end()) {
virtual_identity *p = name_it->second;
if (p->vtable_ptr && p->vtable_ptr != vtable) {
std::cerr << "Conflicting vtable ptr for class '" << p->getName()
@ -103,14 +193,6 @@ virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
return NULL;
}
bool virtual_identity::is_subclass(virtual_identity *actual)
{
for (; actual; actual = actual->parent)
if (actual == this) return true;
return false;
}
void virtual_identity::adjust_vtable(virtual_ptr obj, virtual_identity *main)
{
if (vtable_ptr) {
@ -135,35 +217,6 @@ virtual_ptr virtual_identity::clone(virtual_ptr obj)
return copy;
}
void virtual_identity::Init(Core *core)
{
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;
}
}
//FIXME: ... nuked. the group was empty...
/*
// Read pre-filled vtable ptrs
OffsetGroup *ptr_table = core->vinfo->getGroup("vtable");
for (virtual_identity *p = list; p; p = p->next) {
void * tmp;
if (ptr_table->getSafeAddress(p->getName(),tmp))
p->vtable_ptr = tmp;
}
*/
}
bool DFHack::findBitfieldField(unsigned *idx, const std::string &name,
unsigned size, const bitfield_item_info *items)
{

@ -21,6 +21,8 @@ namespace {
#define INIT_GLOBAL_FUNCTION_ITEM(type,name) \
if (global_table_->getAddress(#name,tmp_)) name = (type*)tmp_;
#define TID(type) (&identity_traits< type >::identity)
// Instantiate all the static objects
#include "df/static.inc"
#include "df/static.enums.inc"

@ -0,0 +1,23 @@
#include "Internal.h"
#include "DataDefs.h"
#include "MiscUtils.h"
#include "VersionInfo.h"
#include "df/world.h"
#include "df/world_data.h"
#include "df/ui.h"
#include "DataIdentity.h"
#include <stddef.h>
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
#define TID(type) (&identity_traits< type >::identity)
#define FLD(mode, name) struct_field_info::mode, #name, offsetof(CUR_STRUCT, name)
#define GFLD(mode, name) struct_field_info::mode, #name, 0
#define FLD_END struct_field_info::END
// Field definitions
#include "df/static.fields.inc"

@ -45,47 +45,205 @@ namespace DFHack
{
class virtual_class {};
enum identity_type {
IDTYPE_GLOBAL,
IDTYPE_PRIMITIVE,
IDTYPE_CONTAINER,
IDTYPE_BITFIELD,
IDTYPE_ENUM,
IDTYPE_STRUCT,
IDTYPE_CLASS
};
typedef void *(*TAllocateFn)(void*,const void*);
class DFHACK_EXPORT type_identity {
size_t size;
protected:
type_identity(size_t size) : size(size) {};
virtual void *do_instantiate() {
void *p = malloc(size);
memset(p, 0, size);
return p;
}
virtual void do_copy(void *tgt, const void *src) {
memmove(tgt, src, size);
};
public:
virtual ~type_identity() {}
size_t byte_size() { return size; }
virtual identity_type type() = 0;
};
class DFHACK_EXPORT constructed_identity : public type_identity {
TAllocateFn allocator;
protected:
constructed_identity(size_t size, TAllocateFn alloc)
: type_identity(size), allocator(alloc) {};
virtual void *do_instantiate() {
return allocator ? allocator(NULL,NULL) : type_identity::do_instantiate();
}
virtual void do_copy(void *tgt, const void *src) {
if (allocator) allocator(tgt,src);
else type_identity::do_copy(tgt, src);
};
};
class DFHACK_EXPORT compound_identity : public constructed_identity {
static compound_identity *list;
compound_identity *next;
const char *dfhack_name;
compound_identity *scope_parent;
std::vector<compound_identity*> scope_children;
static std::vector<compound_identity*> top_scope;
protected:
compound_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name);
virtual void doInit(Core *core);
public:
const char *getName() { return dfhack_name; }
compound_identity *getScopeParent() { return scope_parent; }
const std::vector<compound_identity*> &getScopeChildren() { return scope_children; }
static const std::vector<compound_identity*> &getTopScope() { return top_scope; }
static void Init(Core *core);
};
// Bitfields
struct bitfield_item_info {
const char *name;
int size;
};
class DFHACK_EXPORT bitfield_identity : public compound_identity {
const bitfield_item_info *bits;
int num_bits;
public:
bitfield_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
int num_bits, const bitfield_item_info *bits);
virtual identity_type type() { return IDTYPE_BITFIELD; }
int getNumBits() { return num_bits; }
const bitfield_item_info *getBits() { return bits; }
};
class DFHACK_EXPORT enum_identity : public compound_identity {
const char *const *keys;
int64_t first_item_value;
int64_t last_item_value;
public:
enum_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
int64_t first_item_value, int64_t last_item_value,
const char *const *keys);
virtual identity_type type() { return IDTYPE_ENUM; }
int getCount() { return int(last_item_value-first_item_value+1); }
const char *const *getKeys() { return keys; }
};
struct struct_field_info {
enum Mode {
END,
PRIMITIVE,
STATIC_STRING,
POINTER,
STATIC_ARRAY,
SUBSTRUCT,
CONTAINER,
STL_VECTOR_PTR
};
Mode mode;
const char *name;
size_t offset;
type_identity *type;
size_t count;
enum_identity *eid;
};
class DFHACK_EXPORT struct_identity : public compound_identity {
struct_identity *parent;
std::vector<struct_identity*> children;
bool has_children;
protected:
virtual void doInit(Core *core);
public:
struct_identity(size_t size, TAllocateFn alloc,
compound_identity *scope_parent, const char *dfhack_name,
struct_identity *parent, const struct_field_info *fields);
virtual identity_type type() { return IDTYPE_STRUCT; }
struct_identity *getParent() { return parent; }
const std::vector<struct_identity*> &getChildren() { return children; }
bool hasChildren() { return has_children; }
bool is_subclass(struct_identity *subtype);
};
class DFHACK_EXPORT global_identity : public struct_identity {
public:
global_identity(const struct_field_info *fields)
: struct_identity(0,NULL,NULL,"global",NULL,fields) {}
virtual identity_type type() { return IDTYPE_GLOBAL; }
};
#ifdef _MSC_VER
typedef void *virtual_ptr;
#else
typedef virtual_class *virtual_ptr;
#endif
class DFHACK_EXPORT virtual_identity {
static virtual_identity *list;
class DFHACK_EXPORT virtual_identity : public struct_identity {
static std::map<void*, virtual_identity*> known;
virtual_identity *prev, *next;
const char *dfhack_name;
const char *original_name;
virtual_identity *parent;
std::vector<virtual_identity*> children;
void *vtable_ptr;
bool has_children;
protected:
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
virtual void doInit(Core *core);
static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; }
public:
const char *getName() { return dfhack_name; }
const char *getOriginalName() { return original_name ? original_name : dfhack_name; }
virtual_identity(size_t size, TAllocateFn alloc,
const char *dfhack_name, const char *original_name,
virtual_identity *parent, const struct_field_info *fields);
virtual identity_type type() { return IDTYPE_CLASS; }
virtual_identity *getParent() { return parent; }
const std::vector<virtual_identity*> &getChildren() { return children; }
const char *getOriginalName() { return original_name ? original_name : getName(); }
public:
static virtual_identity *get(virtual_ptr instance_ptr);
bool is_subclass(virtual_identity *subtype);
bool is_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
if (vtable_ptr) {
void *vtable = get_vtable(instance_ptr);
if (vtable == vtable_ptr) return true;
if (!has_children) return false;
if (!hasChildren()) return false;
}
return is_subclass(get(instance_ptr));
}
@ -98,15 +256,10 @@ namespace DFHack
public:
bool can_instantiate() { return (vtable_ptr != NULL); }
virtual_ptr instantiate() { return can_instantiate() ? do_instantiate() : NULL; }
virtual_ptr instantiate() { return can_instantiate() ? (virtual_ptr)do_instantiate() : NULL; }
static virtual_ptr clone(virtual_ptr obj);
protected:
virtual virtual_ptr do_instantiate() = 0;
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) = 0;
public:
static void Init(Core *core);
// Strictly for use in virtual class constructors
void adjust_vtable(virtual_ptr obj, virtual_identity *main);
};
@ -135,12 +288,6 @@ namespace DFHack
size_t size;
const T *items;
};
// Bitfields
struct bitfield_item_info {
const char *name;
int size;
};
}
template<class T>
@ -164,33 +311,37 @@ inline int linear_index(const DFHack::enum_list_attr<const char*> &lst, const st
namespace df
{
using DFHack::type_identity;
using DFHack::compound_identity;
using DFHack::virtual_ptr;
using DFHack::virtual_identity;
using DFHack::virtual_class;
using DFHack::global_identity;
using DFHack::struct_identity;
using DFHack::struct_field_info;
using DFHack::bitfield_item_info;
using DFHack::bitfield_identity;
using DFHack::enum_identity;
using DFHack::enum_list_attr;
using DFHack::BitArray;
using DFHack::DfArray;
template<class T>
struct enum_traits {};
void *allocator_fn(void *out, const void *in) {
if (out) { *(T*)out = *(const T*)in; return out; }
else return new T();
}
template<class T>
struct bitfield_traits {};
struct identity_traits {
static compound_identity *get() { return &T::_identity; }
};
template<class T>
class class_virtual_identity : public virtual_identity {
public:
class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent)
: virtual_identity(dfhack_name, original_name, parent) {};
T *instantiate() { return static_cast<T*>(virtual_identity::instantiate()); }
T *clone(T* obj) { return static_cast<T*>(virtual_identity::clone(obj)); }
struct enum_traits {};
protected:
virtual virtual_ptr do_instantiate() { return new T(); }
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) { *static_cast<T*>(tgt) = *static_cast<T*>(src); }
};
template<class T>
struct bitfield_traits {};
template<class EnumType, class IntType = int32_t>
struct enum_field {

@ -0,0 +1,175 @@
/*
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.
*/
#pragma once
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "DataDefs.h"
/*
* Definitions of DFHack namespace structs used by generated headers.
*/
namespace DFHack
{
class DFHACK_EXPORT primitive_identity : public type_identity {
public:
primitive_identity(size_t size) : type_identity(size) {};
virtual identity_type type() { return IDTYPE_PRIMITIVE; }
};
class DFHACK_EXPORT container_identity : public constructed_identity {
type_identity *item;
enum_identity *ienum;
public:
container_identity(size_t size, TAllocateFn alloc, type_identity *item, enum_identity *ienum = NULL)
: constructed_identity(size, alloc), item(item), ienum(ienum) {};
virtual identity_type type() { return IDTYPE_CONTAINER; }
};
}
namespace df
{
using DFHack::primitive_identity;
using DFHack::container_identity;
#define ATOM_IDENTITY_TRAITS(type) \
template<> struct identity_traits<type> { \
static primitive_identity identity; \
static primitive_identity *get() { return &identity; } \
}; \
primitive_identity identity_traits<type>::identity(sizeof(type));
ATOM_IDENTITY_TRAITS(char);
ATOM_IDENTITY_TRAITS(int8_t);
ATOM_IDENTITY_TRAITS(uint8_t);
ATOM_IDENTITY_TRAITS(int16_t);
ATOM_IDENTITY_TRAITS(uint16_t);
ATOM_IDENTITY_TRAITS(int32_t);
ATOM_IDENTITY_TRAITS(uint32_t);
ATOM_IDENTITY_TRAITS(int64_t);
ATOM_IDENTITY_TRAITS(uint64_t);
ATOM_IDENTITY_TRAITS(bool);
ATOM_IDENTITY_TRAITS(float);
ATOM_IDENTITY_TRAITS(std::string);
ATOM_IDENTITY_TRAITS(void*);
#undef ATOM_IDENTITY_TRAITS
// Container declarations
template<class Enum, class FT> struct identity_traits<enum_field<Enum,FT> > {
static primitive_identity *get();
};
template<class T> struct identity_traits<T *> {
static container_identity *get();
};
template<class T, int sz> struct identity_traits<T [sz]> {
static container_identity *get();
};
template<class T> struct identity_traits<std::vector<T> > {
static container_identity *get();
};
template<class T> struct identity_traits<std::deque<T> > {
static container_identity *get();
};
template<class T> struct identity_traits<BitArray<T> > {
static container_identity *get();
};
template<class T> struct identity_traits<DfArray<T> > {
static container_identity *get();
};
// Container definitions
template<class Enum, class FT>
primitive_identity *identity_traits<enum_field<Enum,FT> >::get() {
static primitive_identity identity(sizeof(FT));
return &identity;
}
template<class T>
container_identity *identity_traits<T *>::get() {
typedef T * container;
static container_identity identity(sizeof(container), &allocator_fn<container>,
identity_traits<T>::get());
return &identity;
}
template<class T, int sz>
container_identity *identity_traits<T [sz]>::get() {
typedef T container[sz];
static container_identity identity(sizeof(container), NULL,
identity_traits<T>::get());
return &identity;
}
template<class T>
container_identity *identity_traits<std::vector<T> >::get() {
typedef std::vector<T> container;
static container_identity identity(sizeof(container), &allocator_fn<container>,
identity_traits<T>::get());
return &identity;
}
template<class T>
container_identity *identity_traits<std::deque<T> >::get() {
typedef std::deque<T> container;
static container_identity identity(sizeof(container), &allocator_fn<container>,
identity_traits<T>::get());
return &identity;
}
template<class T>
container_identity *identity_traits<BitArray<T> >::get() {
typedef BitArray<T> container;
static type_identity *eid = identity_traits<T>::get();
static enum_identity *reid = eid->type() == DFHack::IDTYPE_ENUM ? (enum_identity*)eid : NULL;
static container_identity identity(sizeof(container), &allocator_fn<container>,
&identity_traits<bool>::identity, reid);
return &identity;
}
template<class T>
container_identity *identity_traits<DfArray<T> >::get() {
typedef DfArray<T> container;
static container_identity identity(sizeof(container), &allocator_fn<container>,
identity_traits<T>::get());
return &identity;
}
}

@ -1 +1 @@
Subproject commit 08e1f71e89c1af6b3bef940914ed7f3d8fed89b0
Subproject commit 70eb6b5f35680655d04d9fda79ff7251e21b45ae