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