15 #include "interrogateDatabase.h"
16 #include "config_interrogatedb.h"
17 #include "indexRemapper.h"
18 #include "interrogate_datafile.h"
21 int InterrogateDatabase::_file_major_version = 0;
22 int InterrogateDatabase::_file_minor_version = 0;
23 int InterrogateDatabase::_current_major_version = 2;
24 int InterrogateDatabase::_current_minor_version = 3;
32 InterrogateDatabase() {
47 if (interrogatedb_cat->is_debug()) {
48 interrogatedb_cat->debug()
49 <<
"Creating interrogate database\n";
67 if (interrogatedb_cat->is_debug()) {
68 if (def->library_name == (
const char *)NULL) {
69 interrogatedb_cat->debug()
70 <<
"Got interrogate data for anonymous module\n";
72 interrogatedb_cat->debug()
73 <<
"Got interrogate data for module " << def->library_name <<
"\n";
77 int num_indices = def->next_index - def->first_index;
78 if (num_indices > 0) {
81 def->first_index = _next_index;
82 _next_index += num_indices;
83 def->next_index = _next_index;
88 _modules.push_back(def);
91 if (def->num_unique_names > 0 && def->library_name != (
const char *)NULL) {
94 _modules_by_hash[def->library_hash_name] = def;
97 if (def->database_filename != (
const char *)NULL) {
98 _requests.push_back(def);
128 return _global_types.size();
140 if (n >= 0 && n < (
int)_global_types.size()) {
141 return _global_types[n];
157 return _all_types.size();
169 if (n >= 0 && n < (
int)_all_types.size()) {
170 return _all_types[n];
186 return _global_functions.size();
198 if (n >= 0 && n < (
int)_global_functions.size()) {
199 return _global_functions[n];
215 return _all_functions.size();
227 if (n >= 0 && n < (
int)_all_functions.size()) {
228 return _all_functions[n];
242 return _global_manifests.size();
254 if (n >= 0 && n < (
int)_global_manifests.size()) {
255 return _global_manifests[n];
269 return _global_elements.size();
281 if (n >= 0 && n < (
int)_global_elements.size()) {
282 return _global_elements[n];
298 TypeMap::const_iterator ti;
299 ti = _type_map.find(type);
300 if (ti == _type_map.end()) {
317 FunctionMap::const_iterator fi;
318 fi = _function_map.find(
function);
319 if (fi == _function_map.end()) {
320 return bogus_function;
322 return *(*fi).second;
336 FunctionWrapperMap::const_iterator wi;
337 wi = _wrapper_map.find(wrapper);
338 if (wi == _wrapper_map.end()) {
339 return bogus_wrapper;
355 ManifestMap::const_iterator mi;
356 mi = _manifest_map.find(manifest);
357 if (mi == _manifest_map.end()) {
358 return bogus_manifest;
374 ElementMap::const_iterator ei;
375 ei = _element_map.find(element);
376 if (ei == _element_map.end()) {
377 return bogus_element;
393 MakeSeqMap::const_iterator si;
394 si = _make_seq_map.find(make_seq);
395 if (si == _make_seq_map.end()) {
396 return bogus_make_seq;
408 _type_map.erase(type);
423 if (find_module(wrapper, def, module_index)) {
424 if (module_index >= 0 && module_index < def->num_fptrs) {
425 return def->fptrs[module_index];
445 string library_hash_name = unique_name.substr(0, 4);
446 string wrapper_hash_name = unique_name.substr(4);
449 ModulesByHash::const_iterator mi;
450 mi = _modules_by_hash.find(library_hash_name);
451 if (mi == _modules_by_hash.end()) {
457 binary_search_wrapper_hash(def->unique_names,
458 def->unique_names + def->num_unique_names,
460 if (index_offset >= 0) {
461 return def->first_index + index_offset;
475 return _file_major_version;
486 return _file_minor_version;
498 return _current_major_version;
510 return _current_minor_version;
522 _error_flag = error_flag;
534 return _next_index++;
547 _type_map.insert(TypeMap::value_type(index, type)).second;
554 assert(!old_type.is_fully_defined());
561 _global_types.push_back(index);
563 _all_types.push_back(index);
575 _function_map.insert(FunctionMap::value_type(index,
function)).second;
578 if (function->is_global()) {
579 _global_functions.push_back(index);
581 _all_functions.push_back(index);
594 _wrapper_map.insert(FunctionWrapperMap::value_type(index, wrapper)).second;
607 _manifest_map.insert(ManifestMap::value_type(index, manifest)).second;
610 _global_manifests.push_back(index);
622 _element_map.insert(ElementMap::value_type(index, element)).second;
626 _global_elements.push_back(index);
639 _make_seq_map.insert(MakeSeqMap::value_type(index, make_seq)).second;
653 return _type_map[type];
665 return *_function_map[
function];
677 return _wrapper_map[wrapper];
689 return _manifest_map[manifest];
701 return _element_map[element];
713 return _make_seq_map[make_seq];
748 FunctionWrapperMap new_wrapper_map;
749 FunctionWrapperMap::iterator wi;
750 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
752 new_wrapper_map[first_index] = (*wi).second;
757 FunctionMap new_function_map;
758 FunctionMap::iterator fi;
759 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
761 new_function_map[first_index] = (*fi).second;
765 TypeMap new_type_map;
766 TypeMap::iterator ti;
767 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
768 assert((*ti).first != 0);
770 new_type_map[first_index] = (*ti).second;
774 ManifestMap new_manifest_map;
775 ManifestMap::iterator mi;
776 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
778 new_manifest_map[first_index] = (*mi).second;
782 ElementMap new_element_map;
783 ElementMap::iterator ei;
784 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
786 new_element_map[first_index] = (*ei).second;
790 MakeSeqMap new_make_seq_map;
791 MakeSeqMap::iterator si;
792 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
794 new_make_seq_map[first_index] = (*si).second;
798 _next_index = first_index;
800 _wrapper_map.swap(new_wrapper_map);
801 _function_map.swap(new_function_map);
802 _type_map.swap(new_type_map);
803 _manifest_map.swap(new_manifest_map);
804 _element_map.swap(new_element_map);
805 _make_seq_map.swap(new_make_seq_map);
808 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
809 (*wi).second.remap_indices(remap);
811 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
812 (*fi).second->remap_indices(remap);
814 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
815 (*ti).second.remap_indices(remap);
817 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
818 (*mi).second.remap_indices(remap);
820 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
821 (*ei).second.remap_indices(remap);
823 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
824 (*si).second.remap_indices(remap);
826 GlobalFunctions::iterator gfi;
827 for (gfi = _global_functions.begin(); gfi != _global_functions.end(); ++gfi) {
830 for (gfi = _all_functions.begin(); gfi != _all_functions.end(); ++gfi) {
833 GlobalTypes::iterator gti;
834 for (gti = _global_types.begin(); gti != _global_types.end(); ++gti) {
837 for (gti = _all_types.begin(); gti != _all_types.end(); ++gti) {
840 GlobalManifests::iterator gmi;
841 for (gmi = _global_manifests.begin(); gmi != _global_manifests.end(); ++gmi) {
844 GlobalElements::iterator gei;
845 for (gei = _global_elements.begin(); gei != _global_elements.end(); ++gei) {
861 out << def->file_identifier <<
"\n"
862 << _current_major_version <<
" " << _current_minor_version <<
"\n";
865 idf_output_string(out, def->library_name);
866 idf_output_string(out, def->library_hash_name);
867 idf_output_string(out, def->module_name);
872 out << _function_map.size() <<
"\n";
873 FunctionMap::const_iterator fi;
874 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
875 out << (*fi).first <<
" " << *(*fi).second <<
"\n";
878 out << _wrapper_map.size() <<
"\n";
879 FunctionWrapperMap::const_iterator wi;
880 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
881 out << (*wi).first <<
" " << (*wi).second <<
"\n";
884 out << _type_map.size() <<
"\n";
885 TypeMap::const_iterator ti;
886 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
887 out << (*ti).first <<
" " << (*ti).second <<
"\n";
890 out << _manifest_map.size() <<
"\n";
891 ManifestMap::const_iterator mi;
892 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
893 out << (*mi).first <<
" " << (*mi).second <<
"\n";
896 out << _element_map.size() <<
"\n";
897 ElementMap::const_iterator ei;
898 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
899 out << (*ei).first <<
" " << (*ei).second <<
"\n";
902 out << _make_seq_map.size() <<
"\n";
903 MakeSeqMap::const_iterator si;
904 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
905 out << (*si).first <<
" " << (*si).second <<
"\n";
925 if (!temp.read_new(in, def)) {
929 if (def->first_index == 0 && def->next_index == 0) {
934 if (next != def->next_index) {
935 interrogatedb_cat->error()
936 <<
"Module database file " << def->database_filename
937 <<
" is out of date.\n";
951 void InterrogateDatabase::
953 const DSearchPath &searchpath = interrogatedb_path;
955 Requests copy_requests;
956 copy_requests.swap(_requests);
958 Requests::const_iterator ri;
959 for (ri = copy_requests.begin(); ri != copy_requests.end(); ++ri) {
962 if (def->database_filename != (
char *)NULL) {
963 Filename filename = def->database_filename;
965 if (!pathname.empty() && pathname[0] !=
'/') {
966 pathname = searchpath.
find_file(pathname);
969 if (pathname.empty()) {
970 interrogatedb_cat->error()
971 <<
"Unable to find " << filename <<
" on " << searchpath <<
"\n";
979 interrogatedb_cat->error() <<
"Unable to read " << pathname <<
".\n";
984 input >> file_identifier
985 >> _file_major_version >> _file_minor_version;
987 if (def->file_identifier != 0 &&
988 file_identifier != def->file_identifier) {
989 interrogatedb_cat->warning()
990 <<
"Interrogate data in " << pathname
991 <<
" is out of sync with the compiled-in data"
992 <<
" (" << file_identifier <<
" != " << def->file_identifier <<
").\n";
996 if (_file_major_version != _current_major_version ||
997 _file_minor_version > _current_minor_version) {
998 interrogatedb_cat->error()
999 <<
"Cannot read interrogate data in " << pathname
1000 <<
"; database is version " << _file_major_version <<
"."
1001 << _file_minor_version <<
" while we are expecting "
1002 << _current_major_version <<
"." << _current_minor_version
1007 if (interrogatedb_cat->is_debug()) {
1008 interrogatedb_cat->debug()
1009 <<
"Reading " << filename <<
"\n";
1011 if (!
read(input, def)) {
1012 interrogatedb_cat->error()
1013 <<
"Error reading " << pathname <<
".\n";
1033 bool InterrogateDatabase::
1036 idf_input_string(in, def->library_name);
1037 idf_input_string(in, def->library_hash_name);
1038 idf_input_string(in, def->module_name);
1044 in >> num_functions;
1049 while (num_functions > 0) {
1050 FunctionIndex index;
1052 in >> index >> *
function;
1070 while (num_wrappers > 0) {
1071 FunctionWrapperIndex index;
1073 in >> index >> wrapper;
1090 while (num_types > 0) {
1093 in >> index >> type;
1105 in >> num_manifests;
1110 while (num_manifests > 0) {
1111 ManifestIndex index;
1113 in >> index >> manifest;
1130 while (num_elements > 0) {
1133 in >> index >> element;
1145 in >> num_make_seqs;
1150 while (num_make_seqs > 0) {
1153 in >> index >> make_seq;
1173 void InterrogateDatabase::
1180 map<string, TypeIndex> types_by_name;
1182 TypeMap::const_iterator ti;
1183 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1185 if (type.has_true_name()) {
1186 types_by_name[type.get_true_name()] = (*ti).first;
1192 for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) {
1193 TypeIndex other_type_index = (*ti).first;
1196 if (other_type.has_name()) {
1197 map<string, TypeIndex>::iterator ni;
1198 ni = types_by_name.find(other_type.get_true_name());
1199 if (ni != types_by_name.end()) {
1202 TypeIndex this_type_index = (*ni).second;
1203 remap.
add_mapping(other_type_index, this_type_index);
1210 for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) {
1211 TypeIndex other_type_index = (*ti).first;
1214 if (!remap.
in_map(other_type_index)) {
1216 add_type(other_type_index, other_type);
1221 TypeIndex this_type_index = remap.
map_from(other_type_index);
1227 _global_types.push_back(this_type_index);
1237 FunctionMap::const_iterator fi;
1238 for (fi = other._function_map.begin();
1239 fi != other._function_map.end();
1241 FunctionIndex other_function_index = (*fi).first;
1247 FunctionWrapperMap::const_iterator wi;
1248 for (wi = other._wrapper_map.begin();
1249 wi != other._wrapper_map.end();
1251 FunctionWrapperIndex other_wrapper_index = (*wi).first;
1257 ManifestMap::const_iterator mi;
1258 for (mi = other._manifest_map.begin();
1259 mi != other._manifest_map.end();
1261 ManifestIndex other_manifest_index = (*mi).first;
1267 ElementMap::const_iterator ei;
1268 for (ei = other._element_map.begin();
1269 ei != other._element_map.end();
1271 ElementIndex other_element_index = (*ei).first;
1277 MakeSeqMap::const_iterator si;
1278 for (si = other._make_seq_map.begin();
1279 si != other._make_seq_map.end();
1281 MakeSeqIndex other_make_seq_index = (*si).first;
1302 bool InterrogateDatabase::
1304 int &module_index) {
1305 if (_modules.empty()) {
1309 int mi = binary_search_module(0, _modules.size(), wrapper);
1310 assert(mi >= 0 && mi < (
int)_modules.size());
1312 module_index = wrapper - def->first_index;
1314 return (wrapper < def->next_index);
1323 int InterrogateDatabase::
1324 binary_search_module(
int begin,
int end, FunctionIndex
function) {
1325 int mid = begin + (end - begin) / 2;
1330 int index = _modules[mid]->first_index;
1331 if (index <=
function) {
1332 return binary_search_module(mid, end,
function);
1335 return binary_search_module(begin, mid,
function);
1346 int InterrogateDatabase::
1349 const string &wrapper_hash_name) {
1355 string name = mid->name;
1356 if (name < wrapper_hash_name) {
1357 return binary_search_wrapper_hash(mid, end, wrapper_hash_name);
1359 }
else if (wrapper_hash_name < name) {
1360 return binary_search_wrapper_hash(begin, mid, wrapper_hash_name);
1363 return mid->index_offset;
1372 void InterrogateDatabase::
1373 freshen_types_by_name() {
1374 _types_by_name.clear();
1375 TypeMap::const_iterator ti;
1376 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1377 _types_by_name[(*ti).second.get_name()] = (*ti).first;
1386 void InterrogateDatabase::
1387 freshen_types_by_scoped_name() {
1388 _types_by_scoped_name.clear();
1389 TypeMap::const_iterator ti;
1390 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1391 _types_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first;
1400 void InterrogateDatabase::
1401 freshen_types_by_true_name() {
1402 _types_by_true_name.clear();
1403 TypeMap::const_iterator ti;
1404 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1405 _types_by_true_name[(*ti).second.get_true_name()] = (*ti).first;
1414 void InterrogateDatabase::
1415 freshen_manifests_by_name() {
1416 _manifests_by_name.clear();
1417 ManifestMap::const_iterator ti;
1418 for (ti = _manifest_map.begin(); ti != _manifest_map.end(); ++ti) {
1419 _manifests_by_name[(*ti).second.get_name()] = (*ti).first;
1428 void InterrogateDatabase::
1429 freshen_elements_by_name() {
1430 _elements_by_name.clear();
1431 ElementMap::const_iterator ti;
1432 for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) {
1433 _elements_by_name[(*ti).second.get_name()] = (*ti).first;
1442 void InterrogateDatabase::
1443 freshen_elements_by_scoped_name() {
1444 _elements_by_scoped_name.clear();
1445 ElementMap::const_iterator ti;
1446 for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) {
1447 _elements_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first;
1458 int InterrogateDatabase::
1459 lookup(
const string &name, Lookup &lookup, LookupType type,
1461 if ((_lookups_fresh & (
int)type) == 0) {
1464 _lookups_fresh |= (int)type;
1467 Lookup::const_iterator li;
1468 li = lookup.find(name);
1469 if (li != lookup.end()) {
1470 return (*li).second;
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
InterrogateMakeSeq & update_make_seq(MakeSeqIndex make_seq)
Returns a non-const reference to the indicated make_seq, allowing the user to update it...
static int get_current_major_version()
Returns the major version number currently expected in interrogate database files generated by this c...
static int get_file_minor_version()
Returns the minor version number of the interrogate database file currently being read...
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
const InterrogateManifest & get_manifest(ManifestIndex manifest)
Returns the manifest constant associated with the given ManifestIndex, if there is one...
static int get_current_minor_version()
Returns the minor version number currently expected in interrogate database files generated by this c...
int get_num_global_manifests()
Returns the total number of global manifest constants known to the interrogate database.
This class manages a mapping of integers to integers.
bool is_global() const
Returns true if the type is marked as 'global'.
TypeIndex get_all_type(int n)
Returns the index of the nth type known to the interrogate database.
bool get_error_flag()
Returns the global error flag.
void set_text()
Indicates that the filename represents a text file.
bool open_read(ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
const InterrogateMakeSeq & get_make_seq(MakeSeqIndex element)
Returns the make_seq associated with the given MakeSeqIndex, if there is one.
FunctionIndex get_global_function(int n)
Returns the index of the nth global function known to the interrogate database.
Represents a synthetic method created via the MAKE_SEQ() macro.
InterrogateFunctionWrapper & update_wrapper(FunctionWrapperIndex wrapper)
Returns a non-const reference to the indicated function wrapper, allowing the user to update it...
InterrogateElement & update_element(ElementIndex element)
Returns a non-const reference to the indicated data element, allowing the user to update it...
const InterrogateType & get_type(TypeIndex type)
Returns the type associated with the given TypeIndex, if there is one.
void request_module(InterrogateModuleDef *def)
Requests that the interrogate data for the given module be made available.
static InterrogateDatabase * get_ptr()
Returns the global pointer to the one InterrogateDatabase.
bool in_map(int from) const
Returns true if the given 'from' integer has been assigned a mapping, false if it has not...
ElementIndex get_global_element(int n)
Returns the index of the nth global data element known to the interrogate database.
InterrogateFunction & update_function(FunctionIndex function)
Returns a non-const reference to the indicated function, allowing the user to update it...
InterrogateManifest & update_manifest(ManifestIndex manifest)
Returns a non-const reference to the indicated manifest constant, allowing the user to update it...
This stores all of the interrogate data and handles reading the data from a disk file when necessary...
void * get_fptr(FunctionWrapperIndex wrapper)
Returns the function pointer associated with the given function wrapper, if it has a pointer availabl...
TypeIndex get_global_type(int n)
Returns the index of the nth global type known to the interrogate database.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
FunctionWrapperIndex get_wrapper_by_unique_name(const string &unique_name)
Looks up the function wrapper corresponding to the given unique name, if available.
int get_num_global_functions()
Returns the total number of global functions known to the interrogate database.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
An internal representation of a type.
FunctionIndex get_all_function(int n)
Returns the index of the nth function known to the interrogate database.
void set_error_flag(bool error_flag)
Sets the global error flag.
void add_type(TypeIndex index, const InterrogateType &type)
Adds the indicated type to the database at the given index number.
InterrogateType & update_type(TypeIndex type)
Returns a non-const reference to the indicated type, allowing the user to update it.
static int get_file_major_version()
Returns the major version number of the interrogate database file currently being read...
An internal representation of a function.
An internal representation of a callable function.
void clear()
Removes all mappings from the object.
The name of a file, such as a texture file or an Egg file.
void add_element(ElementIndex index, const InterrogateElement &element)
Adds the indicated data element to the database at the given index number.
void add_function(FunctionIndex index, InterrogateFunction *function)
Adds the indicated function to the database at the given index number.
ManifestIndex get_global_manifest(int n)
Returns the index of the nth global manifest constant known to the interrogate database.
An internal representation of a manifest constant.
int get_next_index()
Returns a new index number suitable for the next thing, that will not be shared with any other index ...
const InterrogateElement & get_element(ElementIndex element)
Returns the data element associated with the given ElementIndex, if there is one. ...
void add_wrapper(FunctionWrapperIndex index, const InterrogateFunctionWrapper &wrapper)
Adds the indicated function wrapper to the database at the given index number.
int get_num_global_types()
Returns the total number of "global" types known to the interrogate database.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
bool read(istream &in, InterrogateModuleDef *def)
Reads a database from the indicated stream, associated with the indicated module definition and merge...
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
Filename find_file(const Filename &filename) const
Searches all the directories in the search list for the indicated file, in order. ...
bool is_global() const
Returns true if the element is marked as 'global'.
An internal representation of a data element, like a data member or a global variable.
const InterrogateFunctionWrapper & get_wrapper(FunctionWrapperIndex wrapper)
Returns the function wrapper associated with the given FunctionWrapperIndex, if there is one...
This class stores a list of directories that can be searched, in order, to locate a particular file...
int get_num_all_functions()
Returns the total number of functions known to the interrogate database.
void add_manifest(ManifestIndex index, const InterrogateManifest &manifest)
Adds the indicated manifest constant to the database at the given index number.
int map_from(int from) const
Returns the integer that the given 'from' integer had been set to map to, or the same integer if noth...
void add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq)
Adds the indicated make_seq to the database at the given index number.
void merge_with(const InterrogateType &other)
Combines type with the other similar definition.
void add_mapping(int from, int to)
Adds a mapping from the integer 'from' to 'to'.
void remove_type(TypeIndex type)
Erases the type from the database.
int get_num_all_types()
Returns the total number of types known to the interrogate database.
int get_num_global_elements()
Returns the total number of global data elements known to the interrogate database.
const InterrogateFunction & get_function(FunctionIndex function)
Returns the function associated with the given FunctionIndex, if there is one.
int remap_indices(int first_index)
Resequences all of the various index numbers so that all of the functions start at first_index and in...
void write(ostream &out, InterrogateModuleDef *def) const
Writes the database to the indicated stream for later reading.