Panda3D
Loading...
Searching...
No Matches
interrogateDatabase.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file interrogateDatabase.cxx
10 * @author drose
11 * @date 2000-08-01
12 */
13
14#include "interrogateDatabase.h"
16#include "indexRemapper.h"
18
19using std::map;
20using std::string;
21
22InterrogateDatabase *InterrogateDatabase::_global_ptr = nullptr;
23int InterrogateDatabase::_file_major_version = 0;
24int InterrogateDatabase::_file_minor_version = 0;
25int InterrogateDatabase::_current_major_version = 3;
26int InterrogateDatabase::_current_minor_version = 3;
27
28/**
29 *
30 */
31InterrogateDatabase::
32InterrogateDatabase() {
33 _error_flag = false;
34 _next_index = 1;
35 _lookups_fresh = 0;
36}
37
38/**
39 * Returns the global pointer to the one InterrogateDatabase.
40 */
42get_ptr() {
43 if (_global_ptr == nullptr) {
44 if (interrogatedb_cat->is_debug()) {
45 interrogatedb_cat->debug()
46 << "Creating interrogate database\n";
47 }
48 _global_ptr = new InterrogateDatabase;
49 }
50 return _global_ptr;
51}
52
53/**
54 * Requests that the interrogate data for the given module be made available.
55 * The function pointers will be made available immediately, while the
56 * database file will be read later, the next time someone asks for
57 * interrogate data that requires it.
58 */
61 if (interrogatedb_cat->is_debug()) {
62 if (def->library_name == nullptr) {
63 interrogatedb_cat->debug()
64 << "Got interrogate data for anonymous module\n";
65 } else {
66 interrogatedb_cat->debug()
67 << "Got interrogate data for module " << def->library_name << "\n";
68 }
69 }
70
71 int num_indices = def->next_index - def->first_index;
72 if (num_indices > 0) {
73 // If the module def has any definitions--any index numbers used--assign
74 // it to its own unique range of index numbers.
75 def->first_index = _next_index;
76 _next_index += num_indices;
77 def->next_index = _next_index;
78
79 // Assign a reference to the module def by index number. When we need to
80 // look up a function by its index number, we'll be able to use this.
81 _modules.push_back(def);
82 }
83
84 if (def->num_unique_names > 0 && def->library_name != nullptr) {
85 // Define a lookup by hash for this module, mainly so we can look up
86 // functions by their unique names.
87 _modules_by_hash[def->library_hash_name] = def;
88 }
89
90 if (def->database_filename != nullptr) {
91 _requests.push_back(def);
92 }
93}
94
95/**
96 * Returns the global error flag. This will be set true if there was some
97 * problem importing the database (e.g. cannot find an .in file), or false if
98 * everything is ok.
99 */
102 return _error_flag;
103}
104
105/**
106 * Returns the total number of "global" types known to the interrogate
107 * database. These are types defined at the global level that should be
108 * considered for exporting, but not the incidental types (like pointers,
109 * etc.) that must be defined to support these.
110 */
113 check_latest();
114 return _global_types.size();
115}
116
117/**
118 * Returns the index of the nth global type known to the interrogate database.
119 */
121get_global_type(int n) {
122 check_latest();
123 if (n >= 0 && n < (int)_global_types.size()) {
124 return _global_types[n];
125 }
126 return 0;
127}
128
129/**
130 * Returns the total number of types known to the interrogate database. This
131 * includes all known types, global as well as incidental. See also
132 * get_num_global_types().
133 */
136 check_latest();
137 return _all_types.size();
138}
139
140/**
141 * Returns the index of the nth type known to the interrogate database.
142 */
144get_all_type(int n) {
145 check_latest();
146 if (n >= 0 && n < (int)_all_types.size()) {
147 return _all_types[n];
148 }
149 return 0;
150}
151
152/**
153 * Returns the total number of global functions known to the interrogate
154 * database. These are functions defined at the global level, e.g. non-
155 * member functions.
156 */
159 check_latest();
160 return _global_functions.size();
161}
162
163/**
164 * Returns the index of the nth global function known to the interrogate
165 * database.
166 */
168get_global_function(int n) {
169 check_latest();
170 if (n >= 0 && n < (int)_global_functions.size()) {
171 return _global_functions[n];
172 }
173 return 0;
174}
175
176/**
177 * Returns the total number of functions known to the interrogate database.
178 * This includes all known functions, global, method, or synthesized. See
179 * also get_num_global_functions().
180 */
183 check_latest();
184 return _all_functions.size();
185}
186
187/**
188 * Returns the index of the nth function known to the interrogate database.
189 */
191get_all_function(int n) {
192 check_latest();
193 if (n >= 0 && n < (int)_all_functions.size()) {
194 return _all_functions[n];
195 }
196 return 0;
197}
198
199/**
200 * Returns the total number of global manifest constants known to the
201 * interrogate database.
202 */
205 check_latest();
206 return _global_manifests.size();
207}
208
209/**
210 * Returns the index of the nth global manifest constant known to the
211 * interrogate database.
212 */
214get_global_manifest(int n) {
215 check_latest();
216 if (n >= 0 && n < (int)_global_manifests.size()) {
217 return _global_manifests[n];
218 }
219 return 0;
220}
221
222/**
223 * Returns the total number of global data elements known to the interrogate
224 * database.
225 */
228 check_latest();
229 return _global_elements.size();
230}
231
232/**
233 * Returns the index of the nth global data element known to the interrogate
234 * database.
235 */
237get_global_element(int n) {
238 check_latest();
239 if (n >= 0 && n < (int)_global_elements.size()) {
240 return _global_elements[n];
241 }
242 return 0;
243}
244
245/**
246 * Returns the type associated with the given TypeIndex, if there is one.
247 */
249get_type(TypeIndex type) {
250 static InterrogateType bogus_type;
251
252 check_latest();
253 TypeMap::const_iterator ti;
254 ti = _type_map.find(type);
255 if (ti == _type_map.end()) {
256 return bogus_type;
257 }
258 return (*ti).second;
259}
260
261/**
262 * Returns the function associated with the given FunctionIndex, if there is
263 * one.
264 */
266get_function(FunctionIndex function) {
267 static InterrogateFunction bogus_function;
268
269 check_latest();
270 FunctionMap::const_iterator fi;
271 fi = _function_map.find(function);
272 if (fi == _function_map.end()) {
273 return bogus_function;
274 }
275 return *(*fi).second;
276}
277
278/**
279 * Returns the function wrapper associated with the given
280 * FunctionWrapperIndex, if there is one.
281 */
283get_wrapper(FunctionWrapperIndex wrapper) {
284 static InterrogateFunctionWrapper bogus_wrapper;
285
286 check_latest();
287 FunctionWrapperMap::const_iterator wi;
288 wi = _wrapper_map.find(wrapper);
289 if (wi == _wrapper_map.end()) {
290 return bogus_wrapper;
291 }
292 return (*wi).second;
293}
294
295/**
296 * Returns the manifest constant associated with the given ManifestIndex, if
297 * there is one.
298 */
300get_manifest(ManifestIndex manifest) {
301 static InterrogateManifest bogus_manifest;
302
303 check_latest();
304 ManifestMap::const_iterator mi;
305 mi = _manifest_map.find(manifest);
306 if (mi == _manifest_map.end()) {
307 return bogus_manifest;
308 }
309 return (*mi).second;
310}
311
312/**
313 * Returns the data element associated with the given ElementIndex, if there
314 * is one.
315 */
317get_element(ElementIndex element) {
318 static InterrogateElement bogus_element;
319
320 check_latest();
321 ElementMap::const_iterator ei;
322 ei = _element_map.find(element);
323 if (ei == _element_map.end()) {
324 return bogus_element;
325 }
326 return (*ei).second;
327}
328
329/**
330 * Returns the make_seq associated with the given MakeSeqIndex, if there is
331 * one.
332 */
334get_make_seq(MakeSeqIndex make_seq) {
335 static InterrogateMakeSeq bogus_make_seq;
336
337 check_latest();
338 MakeSeqMap::const_iterator si;
339 si = _make_seq_map.find(make_seq);
340 if (si == _make_seq_map.end()) {
341 return bogus_make_seq;
342 }
343 return (*si).second;
344}
345
346/**
347 * Erases the type from the database.
348 */
350remove_type(TypeIndex type) {
351 _type_map.erase(type);
352}
353
354/**
355 * Returns the function pointer associated with the given function wrapper, if
356 * it has a pointer available. Returns NULL if the pointer is not available.
357 */
359get_fptr(FunctionWrapperIndex wrapper) {
361 int module_index;
362 if (find_module(wrapper, def, module_index)) {
363 if (module_index >= 0 && module_index < def->num_fptrs) {
364 return def->fptrs[module_index];
365 }
366 }
367 return nullptr;
368}
369
370/**
371 * Looks up the function wrapper corresponding to the given unique name, if
372 * available. Returns the corresponding wrapper index, or 0 if no such
373 * wrapper is found.
374 */
375FunctionWrapperIndex InterrogateDatabase::
376get_wrapper_by_unique_name(const string &unique_name) {
377 // First, split the unique_name into a library_hash_name and a
378 // wrapper_hash_name.
379
380 // The first four characters are always the library_name.
381 string library_hash_name = unique_name.substr(0, 4);
382 string wrapper_hash_name = unique_name.substr(4);
383
384 // Is the library_name defined?
385 ModulesByHash::const_iterator mi;
386 mi = _modules_by_hash.find(library_hash_name);
387 if (mi == _modules_by_hash.end()) {
388 return 0;
389 }
390
391 InterrogateModuleDef *def = (*mi).second;
392 int index_offset =
393 binary_search_wrapper_hash(def->unique_names,
394 def->unique_names + def->num_unique_names,
395 wrapper_hash_name);
396 if (index_offset >= 0) {
397 return def->first_index + index_offset;
398 }
399
400 return 0;
401}
402
403/**
404 * Returns the major version number of the interrogate database file currently
405 * being read.
406 */
409 return _file_major_version;
410}
411
412/**
413 * Returns the minor version number of the interrogate database file currently
414 * being read.
415 */
418 return _file_minor_version;
419}
420
421/**
422 * Returns the major version number currently expected in interrogate database
423 * files generated by this code base.
424 */
427 return _current_major_version;
428}
429
430/**
431 * Returns the minor version number currently expected in interrogate database
432 * files generated by this code base.
433 */
436 return _current_minor_version;
437}
438
439/**
440 * Sets the global error flag. This should be set true if there was some
441 * problem importing the database (e.g. cannot find an .in file).
442 */
444set_error_flag(bool error_flag) {
445 _error_flag = error_flag;
446}
447
448/**
449 * Returns a new index number suitable for the next thing, that will not be
450 * shared with any other index numbers.
451 */
454 return _next_index++;
455}
456
457/**
458 * Adds the indicated type to the database at the given index number.
459 */
461add_type(TypeIndex index, const InterrogateType &type) {
462 assert(index != 0);
463 bool inserted =
464 _type_map.insert(TypeMap::value_type(index, type)).second;
465
466 if (!inserted) {
467 // If there was already a type at that index, maybe it was a forward
468 // reference. If its _fully_defined bit isn't set, then it's ok.
469 InterrogateType &old_type = _type_map[index];
470 assert(!old_type.is_fully_defined());
471
472 // It was a forward reference. Merge it with the new one.
473 old_type.merge_with(type);
474 }
475
476 if (type.is_global()) {
477 _global_types.push_back(index);
478 }
479 _all_types.push_back(index);
480}
481
482/**
483 * Adds the indicated function to the database at the given index number.
484 */
486add_function(FunctionIndex index, InterrogateFunction *function) {
487 bool inserted =
488 _function_map.insert(FunctionMap::value_type(index, function)).second;
489 assert(inserted);
490
491 if (function->is_global()) {
492 _global_functions.push_back(index);
493 }
494 _all_functions.push_back(index);
495}
496
497/**
498 * Adds the indicated function wrapper to the database at the given index
499 * number.
500 */
502add_wrapper(FunctionWrapperIndex index,
503 const InterrogateFunctionWrapper &wrapper) {
504 bool inserted =
505 _wrapper_map.insert(FunctionWrapperMap::value_type(index, wrapper)).second;
506 assert(inserted);
507}
508
509/**
510 * Adds the indicated manifest constant to the database at the given index
511 * number.
512 */
514add_manifest(ManifestIndex index, const InterrogateManifest &manifest) {
515 bool inserted =
516 _manifest_map.insert(ManifestMap::value_type(index, manifest)).second;
517 assert(inserted);
518
519 _global_manifests.push_back(index);
520}
521
522/**
523 * Adds the indicated data element to the database at the given index number.
524 */
526add_element(ElementIndex index, const InterrogateElement &element) {
527 bool inserted =
528 _element_map.insert(ElementMap::value_type(index, element)).second;
529 assert(inserted);
530
531 if (element.is_global()) {
532 _global_elements.push_back(index);
533 }
534}
535
536/**
537 * Adds the indicated make_seq to the database at the given index number.
538 */
540add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq) {
541 bool inserted =
542 _make_seq_map.insert(MakeSeqMap::value_type(index, make_seq)).second;
543 assert(inserted);
544}
545
546/**
547 * Returns a non-const reference to the indicated type, allowing the user to
548 * update it.
549 */
551update_type(TypeIndex type) {
552 assert(type != 0);
553 check_latest();
554 return _type_map[type];
555}
556
557/**
558 * Returns a non-const reference to the indicated function, allowing the user
559 * to update it.
560 */
562update_function(FunctionIndex function) {
563 check_latest();
564 return *_function_map[function];
565}
566
567/**
568 * Returns a non-const reference to the indicated function wrapper, allowing
569 * the user to update it.
570 */
572update_wrapper(FunctionWrapperIndex wrapper) {
573 check_latest();
574 return _wrapper_map[wrapper];
575}
576
577/**
578 * Returns a non-const reference to the indicated manifest constant, allowing
579 * the user to update it.
580 */
582update_manifest(ManifestIndex manifest) {
583 check_latest();
584 return _manifest_map[manifest];
585}
586
587/**
588 * Returns a non-const reference to the indicated data element, allowing the
589 * user to update it.
590 */
592update_element(ElementIndex element) {
593 check_latest();
594 return _element_map[element];
595}
596
597/**
598 * Returns a non-const reference to the indicated make_seq, allowing the user
599 * to update it.
600 */
602update_make_seq(MakeSeqIndex make_seq) {
603 check_latest();
604 return _make_seq_map[make_seq];
605}
606
607/**
608 * Resequences all of the various index numbers so that all of the functions
609 * start at first_index and increment consecutively from there, and then all
610 * of the types follow. Returns the next available index number.
611 */
613remap_indices(int first_index) {
614 IndexRemapper remap;
615 return remap_indices(first_index, remap);
616}
617
618/**
619 * This flavor of remap_indices() accepts a map that should be empty on
620 * initial call, and will be filled with the mapping of old index number to
621 * new index number. This allows the caller to update its own data structures
622 * to match the new index numbers.
623 */
625remap_indices(int first_index, IndexRemapper &remap) {
626 remap.clear();
627
628 // First, build up the complete map.
629
630 // Get the wrapper indices first. This is important, because the
631 // InterrogateBuilder wants these to be first, and consecutive.
632 FunctionWrapperMap new_wrapper_map;
633 FunctionWrapperMap::iterator wi;
634 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
635 remap.add_mapping((*wi).first, first_index);
636 new_wrapper_map[first_index] = (*wi).second;
637 first_index++;
638 }
639
640 // Everything else can follow; it doesn't matter so much.
641 FunctionMap new_function_map;
642 FunctionMap::iterator fi;
643 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
644 remap.add_mapping((*fi).first, first_index);
645 new_function_map[first_index] = (*fi).second;
646 first_index++;
647 }
648
649 TypeMap new_type_map;
650 TypeMap::iterator ti;
651 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
652 assert((*ti).first != 0);
653 remap.add_mapping((*ti).first, first_index);
654 new_type_map[first_index] = (*ti).second;
655 first_index++;
656 }
657
658 ManifestMap new_manifest_map;
659 ManifestMap::iterator mi;
660 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
661 remap.add_mapping((*mi).first, first_index);
662 new_manifest_map[first_index] = (*mi).second;
663 first_index++;
664 }
665
666 ElementMap new_element_map;
667 ElementMap::iterator ei;
668 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
669 remap.add_mapping((*ei).first, first_index);
670 new_element_map[first_index] = (*ei).second;
671 first_index++;
672 }
673
674 MakeSeqMap new_make_seq_map;
675 MakeSeqMap::iterator si;
676 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
677 remap.add_mapping((*si).first, first_index);
678 new_make_seq_map[first_index] = (*si).second;
679 first_index++;
680 }
681
682 _next_index = first_index;
683
684 _wrapper_map.swap(new_wrapper_map);
685 _function_map.swap(new_function_map);
686 _type_map.swap(new_type_map);
687 _manifest_map.swap(new_manifest_map);
688 _element_map.swap(new_element_map);
689 _make_seq_map.swap(new_make_seq_map);
690
691 // Then, go back through and update all of the internal references.
692 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
693 (*wi).second.remap_indices(remap);
694 }
695 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
696 (*fi).second->remap_indices(remap);
697 }
698 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
699 (*ti).second.remap_indices(remap);
700 }
701 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
702 (*mi).second.remap_indices(remap);
703 }
704 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
705 (*ei).second.remap_indices(remap);
706 }
707 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
708 (*si).second.remap_indices(remap);
709 }
710 GlobalFunctions::iterator gfi;
711 for (gfi = _global_functions.begin(); gfi != _global_functions.end(); ++gfi) {
712 (*gfi) = remap.map_from(*gfi);
713 }
714 for (gfi = _all_functions.begin(); gfi != _all_functions.end(); ++gfi) {
715 (*gfi) = remap.map_from(*gfi);
716 }
717 GlobalTypes::iterator gti;
718 for (gti = _global_types.begin(); gti != _global_types.end(); ++gti) {
719 (*gti) = remap.map_from(*gti);
720 }
721 for (gti = _all_types.begin(); gti != _all_types.end(); ++gti) {
722 (*gti) = remap.map_from(*gti);
723 }
724 GlobalManifests::iterator gmi;
725 for (gmi = _global_manifests.begin(); gmi != _global_manifests.end(); ++gmi) {
726 (*gmi) = remap.map_from(*gmi);
727 }
728 GlobalElements::iterator gei;
729 for (gei = _global_elements.begin(); gei != _global_elements.end(); ++gei) {
730 (*gei) = remap.map_from(*gei);
731 }
732
733 return _next_index;
734}
735
736/**
737 * Writes the database to the indicated stream for later reading.
738 */
740write(std::ostream &out, InterrogateModuleDef *def) const {
741 // Write out the file header.
742 out << def->file_identifier << "\n"
743 << _current_major_version << " " << _current_minor_version << "\n";
744
745 // Write out the module definition.
746 idf_output_string(out, def->library_name);
747 idf_output_string(out, def->library_hash_name);
748 idf_output_string(out, def->module_name);
749 out << "\n";
750
751 // Now write out the components.
752
753 out << _function_map.size() << "\n";
754 FunctionMap::const_iterator fi;
755 for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) {
756 out << (*fi).first << " " << *(*fi).second << "\n";
757 }
758
759 out << _wrapper_map.size() << "\n";
760 FunctionWrapperMap::const_iterator wi;
761 for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
762 out << (*wi).first << " " << (*wi).second << "\n";
763 }
764
765 out << _type_map.size() << "\n";
766 TypeMap::const_iterator ti;
767 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
768 out << (*ti).first << " " << (*ti).second << "\n";
769 }
770
771 out << _manifest_map.size() << "\n";
772 ManifestMap::const_iterator mi;
773 for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) {
774 out << (*mi).first << " " << (*mi).second << "\n";
775 }
776
777 out << _element_map.size() << "\n";
778 ElementMap::const_iterator ei;
779 for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
780 out << (*ei).first << " " << (*ei).second << "\n";
781 }
782
783 out << _make_seq_map.size() << "\n";
784 MakeSeqMap::const_iterator si;
785 for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
786 out << (*si).first << " " << (*si).second << "\n";
787 }
788}
789
790/**
791 * Reads a database from the indicated stream, associated with the indicated
792 * module definition and merges it with any existing data in the database,
793 * according to the expected index numbers specified in the module def. The
794 * header information has already been read.
795 *
796 * Returns true if the file is read successfully, false if there is an error.
797 */
799read(std::istream &in, InterrogateModuleDef *def) {
801 if (!temp.read_new(in, def)) {
802 return false;
803 }
804
805 if (def->first_index == 0 && def->next_index == 0) {
806 _next_index = temp.remap_indices(_next_index);
807
808 } else {
809 int next = temp.remap_indices(def->first_index);
810 if (next != def->next_index) {
811 interrogatedb_cat->error()
812 << "Module database file " << def->database_filename
813 << " is out of date.\n";
814 return false;
815 }
816 }
817
818 merge_from(temp);
819 return true;
820}
821
822/**
823 * Reads in the latest interrogate data.
824 */
825void InterrogateDatabase::
826load_latest() {
827 const DSearchPath &searchpath = interrogatedb_path;
828
829 Requests copy_requests;
830 copy_requests.swap(_requests);
831
832 Requests::const_iterator ri;
833 for (ri = copy_requests.begin(); ri != copy_requests.end(); ++ri) {
834 InterrogateModuleDef *def = (*ri);
835
836 if (def->database_filename != nullptr) {
837 Filename filename = def->database_filename;
838 Filename pathname = filename;
839 if (!pathname.empty() && pathname[0] != '/') {
840 pathname = searchpath.find_file(pathname);
841 }
842
843 if (pathname.empty()) {
844 interrogatedb_cat->error()
845 << "Unable to find " << filename << " on " << searchpath << "\n";
846 set_error_flag(true);
847
848 } else {
849
850 pifstream input;
851 pathname.set_text();
852 if (!pathname.open_read(input)) {
853 interrogatedb_cat->error() << "Unable to read " << pathname << ".\n";
854 set_error_flag(true);
855
856 } else {
857 int file_identifier;
858 input >> file_identifier
859 >> _file_major_version >> _file_minor_version;
860
861 if (def->file_identifier != 0 &&
862 file_identifier != def->file_identifier) {
863 interrogatedb_cat->warning()
864 << "Interrogate data in " << pathname
865 << " is out of sync with the compiled-in data"
866 << " (" << file_identifier << " != " << def->file_identifier << ").\n";
867 set_error_flag(true);
868 }
869
870 if (_file_major_version != _current_major_version ||
871 _file_minor_version > _current_minor_version) {
872 interrogatedb_cat->error()
873 << "Cannot read interrogate data in " << pathname
874 << "; database is version " << _file_major_version << "."
875 << _file_minor_version << " while we are expecting "
876 << _current_major_version << "." << _current_minor_version
877 << ".\n";
878 set_error_flag(true);
879
880 } else {
881 if (interrogatedb_cat->is_debug()) {
882 interrogatedb_cat->debug()
883 << "Reading " << filename << "\n";
884 }
885 if (!read(input, def)) {
886 interrogatedb_cat->error()
887 << "Error reading " << pathname << ".\n";
888 set_error_flag(true);
889 }
890 }
891 }
892 }
893 }
894 }
895
896 _requests.clear();
897}
898
899/**
900 * Reads from the indicated stream (the header information has already been
901 * read) into the newly-created database. It is an error if the database
902 * already has some data in it.
903 */
904bool InterrogateDatabase::
905read_new(std::istream &in, InterrogateModuleDef *def) {
906 // We've already read the header. Read the module definition.
907 idf_input_string(in, def->library_name);
908 idf_input_string(in, def->library_hash_name);
909 idf_input_string(in, def->module_name);
910
911 // Now read all of the components.
912
913 { // Functions.
914 int num_functions;
915 in >> num_functions;
916 if (in.fail()) {
917 return false;
918 }
919
920 while (num_functions > 0) {
921 FunctionIndex index;
922 InterrogateFunction *function = new InterrogateFunction(def);
923 in >> index >> *function;
924 if (in.fail()) {
925 delete function;
926 return false;
927 }
928
929 add_function(index, function);
930 num_functions--;
931 }
932 }
933
934 { // Wrappers.
935 int num_wrappers;
936 in >> num_wrappers;
937 if (in.fail()) {
938 return false;
939 }
940
941 while (num_wrappers > 0) {
942 FunctionWrapperIndex index;
943 InterrogateFunctionWrapper wrapper(def);
944 in >> index >> wrapper;
945 if (in.fail()) {
946 return false;
947 }
948
949 add_wrapper(index, wrapper);
950 num_wrappers--;
951 }
952 }
953
954 { // Types.
955 int num_types;
956 in >> num_types;
957 if (in.fail()) {
958 return false;
959 }
960
961 while (num_types > 0) {
962 TypeIndex index;
963 InterrogateType type(def);
964 in >> index >> type;
965 if (in.fail()) {
966 return false;
967 }
968
969 add_type(index, type);
970 num_types--;
971
972 // Older versions of interrogate were not setting these flags.
973 const InterrogateType &itype = get_type(index);
974 FunctionIndex dtor = itype.get_destructor();
975 if (dtor != 0) {
976 update_function(dtor)._flags |= InterrogateFunction::F_destructor;
977 }
978 for (int i = 0; i < itype.number_of_constructors(); ++i) {
979 FunctionIndex ctor = itype.get_constructor(i);
980 update_function(ctor)._flags |= InterrogateFunction::F_constructor;
981 }
982 }
983 }
984
985 { // Manifests.
986 int num_manifests;
987 in >> num_manifests;
988 if (in.fail()) {
989 return false;
990 }
991
992 while (num_manifests > 0) {
993 ManifestIndex index;
994 InterrogateManifest manifest(def);
995 in >> index >> manifest;
996 if (in.fail()) {
997 return false;
998 }
999
1000 add_manifest(index, manifest);
1001 num_manifests--;
1002 }
1003 }
1004
1005 { // Elements.
1006 int num_elements;
1007 in >> num_elements;
1008 if (in.fail()) {
1009 return false;
1010 }
1011
1012 while (num_elements > 0) {
1013 ElementIndex index;
1014 InterrogateElement element(def);
1015 in >> index >> element;
1016 if (in.fail()) {
1017 return false;
1018 }
1019
1020 add_element(index, element);
1021 num_elements--;
1022 }
1023 }
1024
1025 { // MakeSeqs.
1026 int num_make_seqs;
1027 in >> num_make_seqs;
1028 if (in.fail()) {
1029 return false;
1030 }
1031
1032 while (num_make_seqs > 0) {
1033 MakeSeqIndex index;
1034 InterrogateMakeSeq make_seq(def);
1035 in >> index >> make_seq;
1036 if (in.fail()) {
1037 return false;
1038 }
1039
1040 add_make_seq(index, make_seq);
1041 num_make_seqs--;
1042 }
1043 }
1044
1045 return true;
1046}
1047
1048/**
1049 * Copies all the data from the indicated database into this one. It is an
1050 * error if any index numbers are shared between the two databases.
1051 */
1052void InterrogateDatabase::
1053merge_from(const InterrogateDatabase &other) {
1054 // We want to collapse shared types together.
1055 IndexRemapper remap;
1056
1057 // First, we need to build a set of types by name, so we know what types we
1058 // already have.
1059 map<string, TypeIndex> types_by_name;
1060
1061 TypeMap::const_iterator ti;
1062 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1063 const InterrogateType &type = (*ti).second;
1064 if (type.has_true_name()) {
1065 types_by_name[type.get_true_name()] = (*ti).first;
1066 }
1067 }
1068
1069 // Now go through the other set of types and determine the mapping into this
1070 // set.
1071 for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) {
1072 TypeIndex other_type_index = (*ti).first;
1073 const InterrogateType &other_type = (*ti).second;
1074
1075 if (other_type.has_name()) {
1076 map<string, TypeIndex>::iterator ni;
1077 ni = types_by_name.find(other_type.get_true_name());
1078 if (ni != types_by_name.end()) {
1079 // Here's a type that we seem to have in common! We'll have to merge
1080 // them.
1081 TypeIndex this_type_index = (*ni).second;
1082 remap.add_mapping(other_type_index, this_type_index);
1083 }
1084 }
1085 }
1086
1087 // Now that we know the full type-to-type mapping, we can copy the new
1088 // types, one at a time.
1089 for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) {
1090 TypeIndex other_type_index = (*ti).first;
1091 const InterrogateType &other_type = (*ti).second;
1092
1093 if (!remap.in_map(other_type_index)) {
1094 // Here's a new type.
1095 add_type(other_type_index, other_type);
1096 update_type(other_type_index).remap_indices(remap);
1097
1098 } else {
1099 // Here's a type to merge.
1100 TypeIndex this_type_index = remap.map_from(other_type_index);
1101
1102 InterrogateType &this_type = update_type(this_type_index);
1103 if (!this_type.is_global() && other_type.is_global()) {
1104 // If the type is about to become global, we need to add it to our
1105 // global_types list.
1106 _global_types.push_back(this_type_index);
1107 }
1108
1109 InterrogateType merge_type = other_type;
1110 merge_type.remap_indices(remap);
1111 this_type.merge_with(merge_type);
1112 }
1113 }
1114
1115 // And copy all of the functions, wrappers, manifests, and elements.
1116 FunctionMap::const_iterator fi;
1117 for (fi = other._function_map.begin();
1118 fi != other._function_map.end();
1119 ++fi) {
1120 FunctionIndex other_function_index = (*fi).first;
1121 InterrogateFunction *other_function = (*fi).second;
1122 add_function(other_function_index, other_function);
1123 update_function(other_function_index).remap_indices(remap);
1124 }
1125
1126 FunctionWrapperMap::const_iterator wi;
1127 for (wi = other._wrapper_map.begin();
1128 wi != other._wrapper_map.end();
1129 ++wi) {
1130 FunctionWrapperIndex other_wrapper_index = (*wi).first;
1131 const InterrogateFunctionWrapper &other_wrapper = (*wi).second;
1132 add_wrapper(other_wrapper_index, other_wrapper);
1133 update_wrapper(other_wrapper_index).remap_indices(remap);
1134 }
1135
1136 ManifestMap::const_iterator mi;
1137 for (mi = other._manifest_map.begin();
1138 mi != other._manifest_map.end();
1139 ++mi) {
1140 ManifestIndex other_manifest_index = (*mi).first;
1141 const InterrogateManifest &other_manifest = (*mi).second;
1142 add_manifest(other_manifest_index, other_manifest);
1143 update_manifest(other_manifest_index).remap_indices(remap);
1144 }
1145
1146 ElementMap::const_iterator ei;
1147 for (ei = other._element_map.begin();
1148 ei != other._element_map.end();
1149 ++ei) {
1150 ElementIndex other_element_index = (*ei).first;
1151 const InterrogateElement &other_element = (*ei).second;
1152 add_element(other_element_index, other_element);
1153 update_element(other_element_index).remap_indices(remap);
1154 }
1155
1156 MakeSeqMap::const_iterator si;
1157 for (si = other._make_seq_map.begin();
1158 si != other._make_seq_map.end();
1159 ++si) {
1160 MakeSeqIndex other_make_seq_index = (*si).first;
1161 const InterrogateMakeSeq &other_make_seq = (*si).second;
1162 add_make_seq(other_make_seq_index, other_make_seq);
1163 update_make_seq(other_make_seq_index).remap_indices(remap);
1164 }
1165
1166 _lookups_fresh = 0;
1167}
1168
1169/**
1170 * Looks up the wrapper definition in the set of module defs that are loaded
1171 * in at runtime and represent the part of the interrogate database that's
1172 * compiled in.
1173 *
1174 * If the wrapper definition is not found, returns false. If it is found,
1175 * returns true and sets def and module_index to the particular module and the
1176 * index within the module where the wrapper is defined.
1177 */
1178bool InterrogateDatabase::
1179find_module(FunctionWrapperIndex wrapper, InterrogateModuleDef *&def,
1180 int &module_index) {
1181 if (_modules.empty()) {
1182 return false;
1183 }
1184
1185 int mi = binary_search_module(0, _modules.size(), wrapper);
1186 assert(mi >= 0 && mi < (int)_modules.size());
1187 def = _modules[mi];
1188 module_index = wrapper - def->first_index;
1189
1190 return (wrapper < def->next_index);
1191}
1192
1193/**
1194 * Searches for the function module that includes the given function index by
1195 * binary search.
1196 */
1197int InterrogateDatabase::
1198binary_search_module(int begin, int end, FunctionIndex function) {
1199 int mid = begin + (end - begin) / 2;
1200 if (mid == begin) {
1201 return mid;
1202 }
1203
1204 int index = _modules[mid]->first_index;
1205 if (index <= function) {
1206 return binary_search_module(mid, end, function);
1207
1208 } else {
1209 return binary_search_module(begin, mid, function);
1210 }
1211}
1212
1213/**
1214 * Searches for the particular function wrapper's hash name within a given
1215 * module. Returns the index number local to the module, or -1 if it is not
1216 * found.
1217 */
1218int InterrogateDatabase::
1219binary_search_wrapper_hash(InterrogateUniqueNameDef *begin,
1221 const string &wrapper_hash_name) {
1222 if (end <= begin) {
1223 return -1;
1224 }
1225
1226 InterrogateUniqueNameDef *mid = begin + (end - begin) / 2;
1227 string name = mid->name;
1228 if (name < wrapper_hash_name) {
1229 return binary_search_wrapper_hash(mid, end, wrapper_hash_name);
1230
1231 } else if (wrapper_hash_name < name) {
1232 return binary_search_wrapper_hash(begin, mid, wrapper_hash_name);
1233
1234 } else {
1235 return mid->index_offset;
1236 }
1237}
1238
1239/**
1240 * Builds up the lookup of types by name.
1241 */
1242void InterrogateDatabase::
1243freshen_types_by_name() {
1244 _types_by_name.clear();
1245 TypeMap::const_iterator ti;
1246 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1247 _types_by_name[(*ti).second.get_name()] = (*ti).first;
1248 }
1249}
1250
1251/**
1252 * Builds up the lookup of types by scoped name.
1253 */
1254void InterrogateDatabase::
1255freshen_types_by_scoped_name() {
1256 _types_by_scoped_name.clear();
1257 TypeMap::const_iterator ti;
1258 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1259 _types_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first;
1260 }
1261}
1262
1263/**
1264 * Builds up the lookup of types by true name.
1265 */
1266void InterrogateDatabase::
1267freshen_types_by_true_name() {
1268 _types_by_true_name.clear();
1269 TypeMap::const_iterator ti;
1270 for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) {
1271 _types_by_true_name[(*ti).second.get_true_name()] = (*ti).first;
1272 }
1273}
1274
1275/**
1276 * Builds up the lookup of manifests by name.
1277 */
1278void InterrogateDatabase::
1279freshen_manifests_by_name() {
1280 _manifests_by_name.clear();
1281 ManifestMap::const_iterator ti;
1282 for (ti = _manifest_map.begin(); ti != _manifest_map.end(); ++ti) {
1283 _manifests_by_name[(*ti).second.get_name()] = (*ti).first;
1284 }
1285}
1286
1287/**
1288 * Builds up the lookup of elements by name.
1289 */
1290void InterrogateDatabase::
1291freshen_elements_by_name() {
1292 _elements_by_name.clear();
1293 ElementMap::const_iterator ti;
1294 for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) {
1295 _elements_by_name[(*ti).second.get_name()] = (*ti).first;
1296 }
1297}
1298
1299/**
1300 * Builds up the lookup of elements by scoped name.
1301 */
1302void InterrogateDatabase::
1303freshen_elements_by_scoped_name() {
1304 _elements_by_scoped_name.clear();
1305 ElementMap::const_iterator ti;
1306 for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) {
1307 _elements_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first;
1308 }
1309}
1310
1311/**
1312 * Looks up a type, manifest, or element in the indicated lookup table by
1313 * name. This is an internal support function.
1314 */
1315int InterrogateDatabase::
1316lookup(const string &name, Lookup &lookup, LookupType type,
1317 void (InterrogateDatabase::*freshen)()) {
1318 if ((_lookups_fresh & (int)type) == 0) {
1319 // The lookup table isn't fresh; we need to freshen it.
1320 (this->*freshen)();
1321 _lookups_fresh |= (int)type;
1322 }
1323
1324 Lookup::const_iterator li;
1325 li = lookup.find(name);
1326 if (li != lookup.end()) {
1327 return (*li).second;
1328 }
1329 return 0;
1330}
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition dSearchPath.h:28
Filename find_file(const Filename &filename) const
Searches all the directories in the search list for the indicated file, in order.
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
void set_text()
Indicates that the filename represents a text file.
Definition filename.I:424
This class manages a mapping of integers to integers.
bool in_map(int from) const
Returns true if the given 'from' integer has been assigned a mapping, false if it has not.
void add_mapping(int from, int to)
Adds a mapping from the integer 'from' to 'to'.
void clear()
Removes all mappings from the object.
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...
This stores all of the interrogate data and handles reading the data from a disk file when necessary.
int get_num_global_types()
Returns the total number of "global" types known to the interrogate database.
void remove_type(TypeIndex type)
Erases the type from the database.
void request_module(InterrogateModuleDef *def)
Requests that the interrogate data for the given module be made available.
ManifestIndex get_global_manifest(int n)
Returns the index of the nth global manifest constant known to the interrogate database.
const InterrogateFunction & get_function(FunctionIndex function)
Returns the function associated with the given FunctionIndex, if there is one.
InterrogateFunction & update_function(FunctionIndex function)
Returns a non-const reference to the indicated function, allowing the user to update it.
static int get_current_minor_version()
Returns the minor version number currently expected in interrogate database files generated by this c...
InterrogateType & update_type(TypeIndex type)
Returns a non-const reference to the indicated type, allowing the user to update it.
int get_num_all_functions()
Returns the total number of functions known to the interrogate database.
InterrogateElement & update_element(ElementIndex element)
Returns a non-const reference to the indicated data element, allowing the user to update it.
int get_num_all_types()
Returns the total number of types 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.
const InterrogateMakeSeq & get_make_seq(MakeSeqIndex element)
Returns the make_seq associated with the given MakeSeqIndex, if there is one.
bool get_error_flag()
Returns the global error flag.
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_elements()
Returns the total number of global data elements known to the interrogate database.
void add_type(TypeIndex index, const InterrogateType &type)
Adds the indicated type to the database at the given index number.
const InterrogateManifest & get_manifest(ManifestIndex manifest)
Returns the manifest constant associated with the given ManifestIndex, if there is one.
const InterrogateType & get_type(TypeIndex type)
Returns the type associated with the given TypeIndex, if there is one.
const InterrogateElement & get_element(ElementIndex element)
Returns the data element associated with the given ElementIndex, if there is one.
int get_num_global_manifests()
Returns the total number of global manifest constants known to the interrogate database.
InterrogateManifest & update_manifest(ManifestIndex manifest)
Returns a non-const reference to the indicated manifest constant, allowing the user to update it.
int get_num_global_functions()
Returns the total number of global functions known to the interrogate database.
InterrogateFunctionWrapper & update_wrapper(FunctionWrapperIndex wrapper)
Returns a non-const reference to the indicated function wrapper, allowing the user to update it.
void add_element(ElementIndex index, const InterrogateElement &element)
Adds the indicated data element to the database at the given index number.
static int get_file_minor_version()
Returns the minor version number of the interrogate database file currently being read.
bool read(std::istream &in, InterrogateModuleDef *def)
Reads a database from the indicated stream, associated with the indicated module definition and merge...
void set_error_flag(bool error_flag)
Sets the global error flag.
const InterrogateFunctionWrapper & get_wrapper(FunctionWrapperIndex wrapper)
Returns the function wrapper associated with the given FunctionWrapperIndex, if there is one.
static int get_current_major_version()
Returns the major version number currently expected in interrogate database files generated by this c...
int get_next_index()
Returns a new index number suitable for the next thing, that will not be shared with any other index ...
static InterrogateDatabase * get_ptr()
Returns the global pointer to the one InterrogateDatabase.
void * get_fptr(FunctionWrapperIndex wrapper)
Returns the function pointer associated with the given function wrapper, if it has a pointer availabl...
FunctionIndex get_all_function(int n)
Returns the index of the nth function known to the interrogate database.
TypeIndex get_all_type(int n)
Returns the index of the nth type known to the interrogate database.
FunctionWrapperIndex get_wrapper_by_unique_name(const std::string &unique_name)
Looks up the function wrapper corresponding to the given unique name, if available.
void add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq)
Adds the indicated make_seq to the database at the given index number.
InterrogateMakeSeq & update_make_seq(MakeSeqIndex make_seq)
Returns a non-const reference to the indicated make_seq, allowing the user to update it.
void add_function(FunctionIndex index, InterrogateFunction *function)
Adds the indicated function to the database at the given index number.
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(std::ostream &out, InterrogateModuleDef *def) const
Writes the database to the indicated stream for later reading.
static int get_file_major_version()
Returns the major version number of the interrogate database file currently being read.
ElementIndex get_global_element(int n)
Returns the index of the nth global data element known to the interrogate database.
TypeIndex get_global_type(int n)
Returns the index of the nth global type known to the interrogate database.
FunctionIndex get_global_function(int n)
Returns the index of the nth global function known to the interrogate database.
An internal representation of a data element, like a data member or a global variable.
bool is_global() const
Returns true if the element is marked as 'global'.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
An internal representation of a callable function.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
An internal representation of a function.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
bool is_global() const
Returns true if the function is marked as 'global'.
Represents a synthetic method created via the MAKE_SEQ() macro.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
An internal representation of a manifest constant.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
An internal representation of a type.
bool is_global() const
Returns true if the type is marked as 'global'.
void merge_with(const InterrogateType &other)
Combines type with the other similar definition.
void remap_indices(const IndexRemapper &remap)
Remaps all internal index numbers according to the indicated map.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void idf_input_string(istream &in, string &str)
Reads the given string from the input file, as previously written by output_string().
void idf_output_string(ostream &out, const string &str, char whitespace)
Writes the indicated string to the output file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.