// file : xsde/cxx/serializer/substitution-map.cxx // author : Boris Kolpackov // copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include // strlen, strcmp, strncmp #ifndef XSDE_EXCEPTIONS # include // assert # include // exit #endif #include #include namespace xsde { namespace cxx { namespace serializer { substitution_map* substitution_map_init::map = 0; size_t substitution_map_init::count = 0; substitution_map:: ~substitution_map () { for (const_iterator i (begin ()), e (end ()); i != e; ++i) { delete *static_cast (const_cast (*i)); } } void substitution_map:: insert (const char* root, const char* member_ns, const char* member_name, const char* member_type) { hashmap* m; if (const void* p = find (root)) m = *static_cast (const_cast (p)); else { m = new hashmap (XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS, sizeof (value)); #ifndef XSDE_EXCEPTIONS if (m == 0 || m->_error () != hashmap::error_none) { error_ = error_no_memory; return; } #endif hashmap::insert (root, &m); #ifndef XSDE_EXCEPTIONS if (_error () != error_none) return; #endif } value v; v.ns_ = member_ns; v.name_ = member_name; m->insert (member_type, &v); #ifndef XSDE_EXCEPTIONS if (m->_error () != hashmap::error_none) error_ = error_no_memory; #endif } bool substitution_map:: check_ (const char*& ns, const char*& name, const char* type) const { size_t h = hash (name); if (ns) { h = hash (h, " ", 1); h = hash (h, ns); } const bucket* p = find (h); if (p == 0) return false; // Search for the entry in the bucket. // const size_t el_size = sizeof (element) + sizeof (hashmap*); const char* b = reinterpret_cast (p) + sizeof (bucket); const char* e = b + p->size_ * el_size; size_t nl = ns ? strlen (name) : 0; for (; b < e; b += el_size) { const element* e = reinterpret_cast (b); if (e->hash_ == h) { if (ns == 0) { if (strcmp (e->key_, name) == 0) break; } else { if (strncmp (e->key_, name, nl) == 0 && e->key_[nl] == ' ' && strcmp (e->key_ + nl + 1, ns) == 0) break; } } } if (b == e) return false; const hashmap* map = *reinterpret_cast ( b + sizeof (element)); // See if we have a direct substitution. // if (const value* v = static_cast (map->find (type))) { ns = v->ns_; name = v->name_; return true; } // Otherwise we have to iterate over possible substitutions and // see if any of them can in turn be substituted with something // that we can use. // for (const_iterator i (map->begin ()), end (map->end ()); i != end; ++i) { const value* v = static_cast (*i); const char* tns = v->ns_; const char* tn = v->name_; if (check_ (tns, tn, type)) { ns = tns; name = tn; return true; } } return false; } // substitution_map_init // substitution_map_init:: substitution_map_init () { if (count == 0) { map = new substitution_map (XSDE_SERIALIZER_SMAP_BUCKETS); #ifndef XSDE_EXCEPTIONS if (map == 0 || map->_error () != substitution_map::error_none) { // This is static initialization so there is nothing we can do. // The best thing is to fail fast. abort() would have probably // been the better choice here but it is not available on some // platforms (notably, WinCE). // assert (false); exit (1); } #endif } ++count; } substitution_map_init:: ~substitution_map_init () { if (--count == 0) delete map; } // substitution_map_entry // substitution_map_entry:: substitution_map_entry (const char* root, const char* member_ns, const char* member_name, const char* member_type) { substitution_map& m = substitution_map_instance (); m.insert (root, member_ns, member_name, member_type); #ifndef XSDE_EXCEPTIONS if (m._error () != substitution_map::error_none) { // This is static initialization so there is nothing we can do. // The best thing is to fail fast. abort() would have probably // been the better choice here but it is not available on some // platforms (notably, WinCE). // assert (false); exit (1); } #endif } // // size_t serializer_smap_elements () { return substitution_map_instance ().size (); } size_t serializer_smap_bucket_elements () { size_t r = 0; substitution_map& m = substitution_map_instance (); for (substitution_map::const_iterator i (m.begin ()), e (m.end ()); i != e; ++i) { const hashmap* h = *static_cast (*i); if (h->size () > r) r = h->size (); } return r; } } } }