Petr Mrázek 2011-12-24 14:27:58 +01:00
commit e9f9f9b92e
16 changed files with 132 additions and 78 deletions

@ -56,7 +56,7 @@ virtual_identity::virtual_identity(const char *dfhack_name, const char *original
static tthread::mutex *known_mutex = NULL;
std::map<void*, virtual_identity*> virtual_identity::known;
virtual_identity *virtual_identity::get(virtual_class *instance_ptr)
virtual_identity *virtual_identity::get(virtual_ptr instance_ptr)
{
if (!instance_ptr) return NULL;
@ -87,7 +87,7 @@ virtual_identity *virtual_identity::get(virtual_class *instance_ptr)
return NULL;
}
bool virtual_identity::check_instance(virtual_class *instance_ptr, bool allow_subclasses)
bool virtual_identity::check_instance(virtual_ptr instance_ptr, bool allow_subclasses)
{
virtual_identity *actual = get(instance_ptr);

@ -1,5 +1,17 @@
#include "Internal.h"
#include "dfhack/DataDefs.h"
#include "dfhack/MiscUtils.h"
#include "dfhack/df/world.h"
#include "dfhack/df/world_data.h"
#include "dfhack/df/ui.h"
namespace {
template<class T>
inline T &_toref(T &r) { return r; }
template<class T>
inline T &_toref(T *&p) { return *p; }
}
// Instantiate all the static objects
#include "dfhack/df/static.inc"

@ -40,6 +40,12 @@ namespace DFHack
{
class virtual_class {};
#ifdef _MSC_VER
typedef void *virtual_ptr;
#else
typedef virtual_class *virtual_ptr;
#endif
class DFHACK_EXPORT virtual_identity {
static virtual_identity *list;
static std::map<void*, virtual_identity*> known;
@ -56,9 +62,9 @@ namespace DFHack
protected:
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
bool check_instance(virtual_class *instance_ptr, bool allow_subclasses);
bool check_instance(virtual_ptr instance_ptr, bool allow_subclasses);
static void *get_vtable(virtual_class *instance_ptr) { return *(void**)instance_ptr; }
static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; }
public:
const char *getName() { return dfhack_name; }
@ -67,9 +73,9 @@ namespace DFHack
virtual_identity *getParent() { return parent; }
const std::vector<virtual_identity*> &getChildren() { return children; }
static virtual_identity *get(virtual_class *instance_ptr);
static virtual_identity *get(virtual_ptr instance_ptr);
bool is_instance(virtual_class *instance_ptr) {
bool is_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
if (vtable_ptr) {
void *vtable = get_vtable(instance_ptr);
@ -79,7 +85,7 @@ namespace DFHack
return check_instance(instance_ptr, true);
}
bool is_direct_instance(virtual_class *instance_ptr) {
bool is_direct_instance(virtual_ptr instance_ptr) {
if (!instance_ptr) return false;
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
: check_instance(instance_ptr, false);
@ -89,12 +95,12 @@ namespace DFHack
};
template<class T>
inline T *virtual_cast(virtual_class *ptr) {
inline T *virtual_cast(virtual_ptr ptr) {
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
}
template<class T>
inline T *strict_virtual_cast(virtual_class *ptr) {
inline T *strict_virtual_cast(virtual_ptr ptr) {
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
}

@ -187,6 +187,7 @@ void print_bits ( T val, DFHack::Console& out )
strs << endl;
out.print(strs.str().c_str());
}
/*
// this is probably completely bogus
std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector<DFHack::t_matgloss> &creature_types)
@ -247,4 +248,21 @@ std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector<DFHack::t_matg
}
*/
template <typename CT, typename FT, typename AT = FT>
CT *binsearch_in_vector(std::vector<CT*> &vec, FT CT::*field, AT value) {
int min = -1, max = (int)vec.size();
CT **p = vec.data();
FT key = (FT)value;
for (;;) {
int mid = (min + max)>>1;
if (mid == min)
return NULL;
FT midv = p[mid]->*field;
if (midv == key)
return p[mid];
else if (midv < key)
min = mid;
else
max = mid;
}
}

@ -56,6 +56,17 @@ sub type_header_def($) {
return uc($main_namespace).'_'.uc($name).'_H';
}
sub translate_lookup($) {
my ($str) = @_;
return undef unless $str && $str =~ /^\$global((\.[_a-zA-Z0-9]+)+)$/;
my @fields = split /\./, substr($1,1);
my $expr = "df::global::".shift(@fields);
for my $fn (@fields) {
$expr = "_toref($expr).$fn";
}
return $expr;
}
# Text generation with indentation
our @lines;
@ -730,6 +741,32 @@ sub get_df_flagarray_type($) {
);
$struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list;
sub emit_find_instance {
my ($tag) = @_;
my $instance_vector = translate_lookup $tag->getAttribute('instance-vector');
if ($instance_vector) {
emit "static std::vector<$typename*> &get_vector();";
emit "static $typename *find(int id);";
with_emit_static {
emit_block {
emit "return ", $instance_vector, ";";
} "std::vector<$typename*>& ${typename}::get_vector() ";
emit_block {
emit "std::vector<$typename*> &vec_ = get_vector();";
if (my $id = $tag->getAttribute('key-field')) {
emit "return binsearch_in_vector(vec_, &${typename}::$id, id_);";
} else {
emit "return (id_ >= 0 && id_ < vec_.size()) ? vec_[id_] : NULL;";
}
} "$typename *${typename}::find(int id_) ";
}
}
}
sub render_struct_type {
my ($tag) = @_;
@ -750,6 +787,8 @@ sub render_struct_type {
with_struct_block {
render_struct_field($_) for get_struct_fields($tag);
emit_find_instance($tag);
if ($has_methods) {
if ($is_class) {
emit "static class_virtual_identity<$typename> _identity;";

@ -7,8 +7,8 @@
<flag-bit name='justice'/>
</bitfield-type>
<class-type type-name='building' original-name='buildingst' key-field='id'>
<code-helper name='find-instance'>(find-by-id $global.world.buildings.all $id $)</code-helper>
<class-type type-name='building' original-name='buildingst'
instance-vector='$global.world.buildings.all' key-field='id'>
<int32_t name='x1' comment='left'/>
<int32_t name='y1'/>

@ -1,5 +1,5 @@
<data-definition>
<struct-type type-name='historical_figure' key-field='id'>
<struct-type type-name='historical_figure' instance-vector='$global.world.history.figures' key-field='id'>
<enum base-type='int16_t' name='profession' type-name='profession'/>
<int16_t name='race' ref-target='creature_raw'/>
@ -17,8 +17,6 @@
<compound type-name='language_name' name='name'/>
<code-helper name='find-instance'>(find-by-id $global.world.history.figures $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
(awhen (find-creature $.race)
@ -44,6 +42,14 @@
<static-array name='unk7' count='5' type-name='int32_t' comment='empty'/>
</struct-type>
<class-type type-name='history_event' original-name='history_eventst'
instance-vector='$global.world.history.events' key-field='id'>
<int32_t name='year'/>
<int32_t name='seconds'/>
<df-flagarray name='flags'/>
<int32_t name='id'/>
</class-type>
<class-type type-name='history_event_masterpiece_createdst' inherits-from='history_event'>
<int32_t name='maker' ref-target='historical_figure'/>
<int32_t name='maker_entity' ref-target='historical_entity'/>

@ -66,9 +66,8 @@
-- CORE ITEM
<class-type type-name='item' original-name='itemst' key-field='id'>
<code-helper name='find-instance'>(find-by-id $global.world.items.all $id $)</code-helper>
<class-type type-name='item' original-name='itemst'
instance-vector='$global.world.items.all' key-field='id'>
<int16_t name='x'/>
<int16_t name='y'/>
<int16_t name='z'/>

@ -190,9 +190,7 @@
<uint8_t name='unk5'/>
</struct-type>
<struct-type type-name='activity_entry' key-field='id'>
<code-helper name='find-instance'>(find-by-id $global.world.activities.all $id $)</code-helper>
<struct-type type-name='activity_entry' instance-vector='$global.world.activities.all' key-field='id'>
<int32_t name='id'/>
<int16_t name='is_individual'/>
<stl-vector name='events'>

@ -18,28 +18,24 @@
<enum-item name='STANDARD_VERB'/>
</enum-type>
<struct-type type-name='language_word' key-field='word'>
<stl-string name='word'/>
<code-helper name='find-instance'>$global.world.raws.language_words[$]</code-helper>
<compound name='forms' is-union='true'>
<static-array type-name='stl-string' name='all' count='9'/>
<compound>
<stl-string name='noun'/>
<stl-string name='noun_plural'/>
<enum-type type-name='part_of_speech'>
<enum-item name='Noun'/>
<enum-item name='NounPlural'/>
<enum-item name='Adjective'/>
<enum-item name='Prefix'/>
<enum-item name='Verb'/>
<enum-item name='Verb3rdPerson'/>
<enum-item name='VerbPast'/>
<enum-item name='VerbPassive'/>
<enum-item name='VerbGerund'/>
</enum-type>
<stl-string name='adjective'/>
<struct-type type-name='language_word' instance-vector='$global.world.raws.language_words'>
<stl-string name='word'/>
<stl-string name='prefix'/>
<code-helper name='describe'>$.word</code-helper>
<stl-string name='verb'/>
<stl-string name='verb_3rd_person'/>
<stl-string name='verb_past'/>
<stl-string name='verb_passive'/>
<stl-string name='verb_gerund'/>
</compound>
</compound>
<static-array type-name='stl-string' name='forms' count='9' index-enum='part_of_speech'/>
<uint8_t name='adj_dist'/>
@ -48,10 +44,10 @@
<df-flagarray name='flags' index-enum='language_word_flags'/>
</struct-type>
<struct-type type-name='language_translation' key-field='name'>
<struct-type type-name='language_translation' instance-vector='$global.world.raws.translations'>
<stl-string name='name'/>
<code-helper name='find-instance'>$global.world.raws.translations[$]</code-helper>
<code-helper name='describe'>$.name</code-helper>
<stl-vector name='unknown1' comment='empty'/>
<stl-vector name='unknown2' comment='empty'/>
@ -78,7 +74,9 @@
<static-array name='words' count='7'>
<int32_t ref-target='language_word'/>
</static-array>
<static-array name='parts_of_speech' count='7' type-name='int16_t'/>
<static-array name='parts_of_speech' count='7'>
<enum base-type='int16_t' type-name='part_of_speech'/>
</static-array>
<int32_t name='language' ref-target='language_translation'/>
<int16_t name='unknown'/>

@ -1,5 +1,5 @@
<data-definition>
<struct-type type-name='historical_entity' key-field='id'>
<struct-type type-name='historical_entity' key-field='id' instance-vector='$global.world.entities.all'>
<int16_t name='unk1'/>
<int32_t name='id' comment='index in the array'/>
<pointer name='entity_raw'/>
@ -9,8 +9,6 @@
<compound name='name' type-name='language_name'/>
<code-helper name='find-instance'>(find-by-id $global.world.entities.all $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
(describe-obj (find-creature $.race))
@ -225,10 +223,9 @@
</compound>
</struct-type>
<struct-type type-name='entity_population' key-field='id'>
<struct-type type-name='entity_population' key-field='id' instance-vector='$global.world.entity_populations'>
<compound name='name' type-name='language_name'/>
<code-helper name='find-instance'>(find-by-id $global.world.entity_populations $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
</code-helper>
@ -258,11 +255,9 @@
<int32_t name='civ_id' ref-target='historical_entity'/>
</struct-type>
<struct-type type-name='nemesis_record' key-field='id'>
<struct-type type-name='nemesis_record' key-field='id' instance-vector='$global.world.nemesis.all'>
<int32_t name='id' comment='sequential index in the array'/>
<code-helper name='find-instance'>(find-by-id $global.world.nemesis.all $id $)</code-helper>
<int32_t name='unit_id' ref-target='unit'/>
<int32_t name='save_file_id' comment='unit-*.dat'/>
@ -284,11 +279,9 @@
<stl-vector name='unk13' type-name='pointer' comment='empty'/>
</struct-type>
<struct-type type-name='artifact_record' key-field='id'>
<struct-type type-name='artifact_record' key-field='id' instance-vector='$global.world.artifacts.all'>
<int32_t name='id'/>
<code-helper name='find-instance'>(find-by-id $global.world.artifacts.all $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
</code-helper>
@ -298,15 +291,6 @@
<int32_t name='unk2'/>
<pointer name='item' type-name='item'/>
</struct-type>
<class-type type-name='history_event' original-name='history_eventst' key-field='id'>
<int32_t name='year'/>
<int32_t name='seconds'/>
<df-flagarray name='flags'/>
<int32_t name='id'/>
<code-helper name='find-instance'>(find-by-id $global.world.history.events $id $)</code-helper>
</class-type>
</data-definition>
<!--

@ -1,15 +1,14 @@
<data-definition>
-- MACHINE
<class-type type-name='machine' original-name='machinest' key-field='id'>
<class-type type-name='machine' original-name='machinest'
instance-vector='$global.world.machines.all' key-field='id'>
<int32_t name="x"/>
<int32_t name="y"/>
<int32_t name="z"/>
<int32_t name="id"/>
<code-helper name='find-instance'>(find-by-id $global.world.machines.all $id $)</code-helper>
<stl-vector name="components">
<pointer>
<int32_t name="building_id" ref-target='building'/>

@ -126,10 +126,10 @@
<static-array name='state_color_str' type-name='stl-string' count='6'/>
</struct-type>
<struct-type type-name='material_plant' key-field='id'>
<struct-type type-name='material_plant' instance-vector='$global.world.raws.plants.all'>
<stl-string name='id'/>
<code-helper name='find-instance'>$global.world.raws.plants.all[$]</code-helper>
<code-helper name='describe'>$.id</code-helper>
<df-flagarray name='flags'/>
@ -234,10 +234,10 @@
<int32_t name='underground_depth_max'/>
</struct-type>
<struct-type type-name='material_inorganic' key-field='id'>
<struct-type type-name='material_inorganic' instance-vector='$global.world.raws.inorganics'>
<stl-string name='id'/>
<code-helper name='find-instance'>$global.world.raws.inorganics.all[$]</code-helper>
<code-helper name='describe'>$.id</code-helper>
<df-flagarray name='flags'/>

@ -111,11 +111,9 @@
<int32_t name="unk_11c"/>
</struct-type>
<struct-type type-name='squad' key-field='id'>
<struct-type type-name='squad' key-field='id' instance-vector='$global.world.squads.all'>
<int32_t name='id'/>
<code-helper name='find-instance'>(find-by-id $global.world.squads.all $id $)</code-helper>
<compound name='name' type-name='language_name'/>
<stl-string name='unk'/>

@ -7,11 +7,10 @@
<stl-string name='code' comment='DWARF_LIAISON etc'/>
</struct-type>
<struct-type type-name='burrow' key-field='id'>
<struct-type type-name='burrow' key-field='id' instance-vector='$global.ui.burrows.list'>
<int32_t name='id'/>
<stl-string name='name'/>
<code-helper name='find-instance'>(find-by-id $global.ui.burrows.list $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
</code-helper>

@ -114,11 +114,9 @@
<flag-bit name='ghostly'/>
</bitfield-type>
<struct-type type-name='unit' key-field='id'>
<struct-type type-name='unit' key-field='id' instance-vector='$global.world.units.all'>
<compound type-name='language_name' name='name'/>
<code-helper name='find-instance'>(find-by-id $global.world.units.all $id $)</code-helper>
<code-helper name='describe'>
(describe-obj $.name)
(awhen (find-creature $.race)