00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "typeRegistry.h"
00020 #include "typedObject.h"
00021 #include "indent.h"
00022 #include "config_express.h"
00023
00024 #include <algorithm>
00025
00026
00027
00028
00029
00030
00031 TypeRegistry *TypeRegistry::_global_pointer = NULL;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 bool TypeRegistry::
00046 register_type(TypeHandle &type_handle, const string &name) {
00047 if (type_handle != TypeHandle::none()) {
00048
00049
00050 TypeRegistryNode *rnode = look_up(type_handle, NULL);
00051 if (&type_handle == &rnode->_ref) {
00052
00053 nassertr(rnode->_name == name, false);
00054 return false;
00055 }
00056 }
00057
00058 NameRegistry::iterator ri;
00059 ri = _name_registry.find(name);
00060
00061 if (ri == _name_registry.end()) {
00062
00063
00064
00065 #ifdef NOTIFY_DEBUG
00066
00067
00068 if (express_cat->is_spam()) {
00069 express_cat->spam() << "Registering type " << name << "\n";
00070 }
00071 #endif
00072
00073 TypeHandle new_handle;
00074 new_handle._index = _handle_registry.size();
00075
00076 TypeRegistryNode *rnode = new TypeRegistryNode(new_handle, name, type_handle);
00077 _handle_registry.push_back(rnode);
00078 _name_registry[name] = rnode;
00079 _derivations_fresh = false;
00080
00081 type_handle = new_handle;
00082 return true;
00083 }
00084 TypeRegistryNode *rnode = (*ri).second;
00085 nassertr(rnode->_name == (*ri).first, false);
00086 nassertr(rnode->_handle._index >= 0 &&
00087 rnode->_handle._index < (int)_handle_registry.size(), false);
00088 nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
00089 nassertr(rnode->_handle._index != 0, false);
00090
00091
00092 if (&type_handle == &rnode->_ref) {
00093
00094
00095 if (type_handle == rnode->_handle) {
00096
00097 return false;
00098 }
00099
00100
00101
00102
00103
00104 express_cat->error()
00105 << "Reregistering " << name << "\n";
00106 type_handle == rnode->_handle;
00107 return false;
00108 }
00109
00110 if (type_handle != rnode->_handle) {
00111
00112 express_cat->warning()
00113 << "Attempt to register type " << name << " more than once!\n";
00114
00115
00116
00117
00118
00119
00120 type_handle = rnode->_handle;
00121 }
00122 return false;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 TypeHandle TypeRegistry::
00135 register_dynamic_type(const string &name) {
00136 NameRegistry::iterator ri;
00137 ri = _name_registry.find(name);
00138
00139 if (ri == _name_registry.end()) {
00140
00141
00142
00143 #ifdef NOTIFY_DEBUG
00144
00145
00146 if (express_cat->is_spam()) {
00147 express_cat->spam() << "Registering type " << name << "\n";
00148 }
00149 #endif
00150
00151
00152
00153
00154 TypeHandle *new_handle = new TypeHandle;
00155 new_handle->_index = _handle_registry.size();
00156
00157 TypeRegistryNode *rnode = new TypeRegistryNode(*new_handle, name, *new_handle);
00158 _handle_registry.push_back(rnode);
00159 _name_registry[name] = rnode;
00160 _derivations_fresh = false;
00161
00162 return *new_handle;
00163 }
00164
00165
00166 TypeRegistryNode *rnode = (*ri).second;
00167 return rnode->_handle;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 void TypeRegistry::
00179 record_derivation(TypeHandle child, TypeHandle parent) {
00180 TypeRegistryNode *cnode = look_up(child, NULL);
00181 nassertv(cnode != (TypeRegistryNode *)NULL);
00182 TypeRegistryNode *pnode = look_up(parent, NULL);
00183 nassertv(pnode != (TypeRegistryNode *)NULL);
00184
00185
00186
00187 TypeRegistryNode::Classes::iterator ni;
00188 ni = find(cnode->_parent_classes.begin(), cnode->_parent_classes.end(),
00189 pnode);
00190
00191 if (ni == cnode->_parent_classes.end()) {
00192 cnode->_parent_classes.push_back(pnode);
00193 pnode->_child_classes.push_back(cnode);
00194 _derivations_fresh = false;
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void TypeRegistry::
00208 record_alternate_name(TypeHandle type, const string &name) {
00209 TypeRegistryNode *rnode = look_up(type, (TypedObject *)NULL);
00210 if (rnode != (TypeRegistryNode *)NULL) {
00211 NameRegistry::iterator ri =
00212 _name_registry.insert(NameRegistry::value_type(name, rnode)).first;
00213 if ((*ri).second != rnode) {
00214 express_cat.warning()
00215 << "Name " << name << " already assigned to TypeHandle "
00216 << rnode->_name << "; cannot reassign to " << type << "\n";
00217 }
00218 }
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228 TypeHandle TypeRegistry::
00229 find_type(const string &name) const {
00230 NameRegistry::const_iterator ri;
00231 ri = _name_registry.find(name);
00232 if (ri == _name_registry.end()) {
00233 return TypeHandle::none();
00234 } else {
00235 return (*ri).second->_handle;
00236 }
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 string TypeRegistry::
00251 get_name(TypeHandle type, TypedObject *object) const {
00252 TypeRegistryNode *rnode = look_up(type, object);
00253 nassertr(rnode != (TypeRegistryNode *)NULL, "");
00254 return rnode->_name;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 int TypeRegistry::
00265 get_num_root_classes() {
00266 freshen_derivations();
00267 return _root_classes.size();
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 TypeHandle TypeRegistry::
00277 get_root_class(int n) {
00278 freshen_derivations();
00279 nassertr(n >= 0 && n < get_num_root_classes(), TypeHandle::none());
00280 return _root_classes[n]->_handle;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 int TypeRegistry::
00300 get_num_parent_classes(TypeHandle child, TypedObject *child_object) const {
00301 TypeRegistryNode *rnode = look_up(child, child_object);
00302 nassertr(rnode != (TypeRegistryNode *)NULL, 0);
00303 return rnode->_parent_classes.size();
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313 TypeHandle TypeRegistry::
00314 get_parent_class(TypeHandle child, int index) const {
00315 TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
00316 nassertr(rnode != (TypeRegistryNode *)NULL, TypeHandle::none());
00317 nassertr(index >= 0 && index < (int)rnode->_parent_classes.size(),
00318 TypeHandle::none());
00319 return rnode->_parent_classes[index]->_handle;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 int TypeRegistry::
00335 get_num_child_classes(TypeHandle child, TypedObject *child_object) const {
00336 TypeRegistryNode *rnode = look_up(child, child_object);
00337 nassertr(rnode != (TypeRegistryNode *)NULL, 0);
00338 return rnode->_child_classes.size();
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348 TypeHandle TypeRegistry::
00349 get_child_class(TypeHandle child, int index) const {
00350 TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
00351 nassertr(rnode != (TypeRegistryNode *)NULL, TypeHandle::none());
00352 nassertr(index >= 0 && index < (int)rnode->_child_classes.size(),
00353 TypeHandle::none());
00354 return rnode->_child_classes[index]->_handle;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 TypeHandle TypeRegistry::
00372 get_parent_towards(TypeHandle child, TypeHandle base,
00373 TypedObject *child_object) {
00374 const TypeRegistryNode *child_node = look_up(child, child_object);
00375 const TypeRegistryNode *base_node = look_up(base, NULL);
00376 nassertr(child_node != (TypeRegistryNode *)NULL &&
00377 base_node != (TypeRegistryNode *)NULL, TypeHandle::none());
00378 freshen_derivations();
00379 return TypeRegistryNode::get_parent_towards(child_node, base_node);
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void TypeRegistry::
00395 reregister_types() {
00396 HandleRegistry::iterator ri;
00397 TypeRegistry *reg = ptr();
00398 for (ri = reg->_handle_registry.begin();
00399 ri != reg->_handle_registry.end();
00400 ++ri) {
00401 TypeRegistryNode *rnode = (*ri);
00402 if (rnode != NULL && rnode->_handle != rnode->_ref) {
00403 express_cat->warning()
00404 << "Reregistering " << rnode->_name << "\n";
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void TypeRegistry::
00418 write(ostream &out) const {
00419
00420
00421 HandleRegistry::const_iterator hi;
00422 for (hi = _handle_registry.begin();
00423 hi != _handle_registry.end();
00424 ++hi) {
00425 const TypeRegistryNode *root = *hi;
00426 if (root != NULL && root->_parent_classes.empty()) {
00427 write_node(out, 2, root);
00428 }
00429 }
00430 }
00431
00432
00433
00434
00435
00436
00437
00438 TypeRegistry *TypeRegistry::
00439 ptr() {
00440 if (_global_pointer == NULL) {
00441 #ifdef NOTIFY_DEBUG
00442 if (express_cat->is_spam()) {
00443 express_cat->spam()
00444 << "Creating global TypeRegistry\n";
00445 }
00446 #endif
00447 init_global_pointer();
00448 }
00449 return _global_pointer;
00450 }
00451
00452
00453
00454
00455
00456
00457 TypeRegistry::
00458 TypeRegistry() {
00459
00460
00461
00462 _handle_registry.push_back(NULL);
00463
00464 _derivations_fresh = false;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 void TypeRegistry::
00476 init_global_pointer() {
00477 _global_pointer = new TypeRegistry;
00478
00479
00480
00481 TypeRegistryNode::_paranoid_inheritance = get_paranoid_inheritance();
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491 void TypeRegistry::
00492 rebuild_derivations() {
00493 #ifdef NOTIFY_DEBUG
00494 express_cat->debug()
00495 << "Rebuilding derivation tree.\n";
00496 #endif
00497
00498
00499
00500 _root_classes.clear();
00501
00502 HandleRegistry::iterator hi;
00503 for (hi = _handle_registry.begin();
00504 hi != _handle_registry.end();
00505 ++hi) {
00506 TypeRegistryNode *node = *hi;
00507 if (node != (TypeRegistryNode *)NULL) {
00508 node->clear_subtree();
00509 }
00510 }
00511
00512
00513
00514 for (hi = _handle_registry.begin();
00515 hi != _handle_registry.end();
00516 ++hi) {
00517 TypeRegistryNode *node = *hi;
00518 if (node != NULL && node->_parent_classes.empty()) {
00519 _root_classes.push_back(node);
00520
00521
00522 node->define_subtree();
00523 }
00524 }
00525 }
00526
00527
00528
00529
00530
00531
00532
00533 void TypeRegistry::
00534 write_node(ostream &out, int indent_level, const TypeRegistryNode *node) const {
00535 indent(out, indent_level) << node->_handle.get_index() << " " << node->_name;
00536 if (!node->_parent_classes.empty()) {
00537 out << " : " << node->_parent_classes[0]->_name;
00538 for (int pi = 1; pi < (int)node->_parent_classes.size(); pi++) {
00539 out << ", " << node->_parent_classes[pi]->_name;
00540 }
00541 }
00542 out << "\n";
00543
00544 for (int i = 0; i < (int)node->_child_classes.size(); i++) {
00545 write_node(out, indent_level + 2, node->_child_classes[i]);
00546 }
00547 }
00548
00549 #ifndef NDEBUG
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 TypeRegistryNode *TypeRegistry::
00568 look_up(TypeHandle handle, TypedObject *object) const {
00569 if (handle._index == 0) {
00570
00571
00572 if (object != NULL) {
00573
00574
00575 handle = object->force_init_type();
00576 if (handle._index == 0) {
00577
00578 express_cat->error()
00579 << "Unable to force_init_type() on unregistered TypeHandle.\n";
00580 nassertr(false, NULL);
00581 }
00582 if (handle == object->get_type()) {
00583
00584 express_cat->warning()
00585 << "Type " << handle << " was unregistered!\n";
00586 } else {
00587
00588
00589
00590 express_cat->error()
00591 << "Attempt to reference unregistered TypeHandle. Type is of some\n"
00592 << "class derived from " << handle << " that doesn't define a good\n"
00593 << "force_init_type() method.\n";
00594 nassertr(false, NULL);
00595 }
00596
00597 } else {
00598
00599
00600 express_cat->error()
00601 << "Attempt to reference unregistered TypeHandle!\n"
00602 << "Registered TypeHandles are:\n";
00603 write(express_cat->error(false));
00604 nassertr(false, NULL);
00605 }
00606 }
00607
00608 if (handle._index < 0 ||
00609 handle._index >= (int)_handle_registry.size()) {
00610 express_cat->fatal()
00611 << "Invalid TypeHandle index " << handle._index
00612 << "! Is memory corrupt?\n";
00613 nassertr(false, NULL);
00614 }
00615
00616 return _handle_registry[handle._index];
00617 }
00618 #endif // NDEBUG
00619