diff options
Diffstat (limited to 'libxsde/xsde/cxx/serializer/substitution-map.cxx')
-rw-r--r-- | libxsde/xsde/cxx/serializer/substitution-map.cxx | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/libxsde/xsde/cxx/serializer/substitution-map.cxx b/libxsde/xsde/cxx/serializer/substitution-map.cxx new file mode 100644 index 0000000..e155882 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/substitution-map.cxx @@ -0,0 +1,248 @@ +// file : xsde/cxx/serializer/substitution-map.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsde/cxx/config.hxx> + +#include <string.h> // strlen, strcmp, strncmp + +#ifndef XSDE_EXCEPTIONS +# include <assert.h> // assert +# include <stdlib.h> // exit +#endif + +#include <xsde/cxx/serializer/substitution-map.hxx> +#include <xsde/cxx/serializer/substitution-map-load.hxx> + +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<hashmap**> (const_cast<void*> (*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<hashmap**> (const_cast<void*> (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<const char*> (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<const element*> (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<const hashmap* const*> ( + b + sizeof (element)); + + // See if we have a direct substitution. + // + if (const value* v = static_cast<const value*> (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<const value*> (*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<const hashmap* const*> (*i); + + if (h->size () > r) + r = h->size (); + } + + return r; + } + } + } +} |