diff options
Diffstat (limited to 'libxsde/xsde/cxx/parser/substitution-map.cxx')
-rw-r--r-- | libxsde/xsde/cxx/parser/substitution-map.cxx | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/libxsde/xsde/cxx/parser/substitution-map.cxx b/libxsde/xsde/cxx/parser/substitution-map.cxx new file mode 100644 index 0000000..950d07d --- /dev/null +++ b/libxsde/xsde/cxx/parser/substitution-map.cxx @@ -0,0 +1,236 @@ +// file : xsde/cxx/parser/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/parser/substitution-map.hxx> +#include <xsde/cxx/parser/substitution-map-load.hxx> + +namespace xsde +{ + namespace cxx + { + namespace parser + { + substitution_map* substitution_map_init::map = 0; + size_t substitution_map_init::count = 0; + + bool substitution_map:: + check_ (const ro_string& ns, + const ro_string& name, + const char* root, + const char** type) const + { + bool r = false; + + if (const value* v = find_ (ns, name)) + { + if (strcmp (root, v->root_) == 0) + r = true; + else + r = check_ (v->root_, root); + + if (r && type != 0 && *type == 0) + *type = v->type_; + } + + return r; + } + + bool substitution_map:: + check_ (const ro_string& ns, + const ro_string& name, + const char* root_ns, + const char* root_name, + const char** type) const + { + bool r = false; + + if (const value* v = find_ (ns, name)) + { + if (root_ns == 0) + r = strcmp (v->root_, root_name) == 0; + else + { + size_t n = strlen (root_name); + + r = strncmp (v->root_, root_name, n) == 0 && v->root_[n] == ' ' && + strcmp (v->root_ + n + 1, root_ns) == 0; + } + + if (!r) + r = check_ (v->root_, root_ns, root_name); + + if (r && type != 0 && *type == 0) + *type = v->type_; + } + + return r; + } + + bool substitution_map:: + check_ (const char* member, const char* root) const + { + const value* v = static_cast<const value*> (find (member)); + + if (v == 0) + return false; + + return strcmp (root, v->root_) == 0 ? true : check_ (v->root_, root); + } + + bool substitution_map:: + check_ (const char* member, + const char* root_ns, + const char* root_name) const + { + const value* v = static_cast<const value*> (find (member)); + + if (v == 0) + return false; + + bool r; + + if (root_ns == 0) + r = strcmp (v->root_, root_name) == 0; + else + { + size_t n = strlen (root_name); + + r = strncmp (v->root_, root_name, n) == 0 && v->root_[n] == ' ' && + strcmp (v->root_ + n + 1, root_ns) == 0; + } + + return r ? true : check_ (v->root_, root_ns, root_name); + } + + const substitution_map::value* substitution_map:: + find_ (const ro_string& ns, const ro_string& name) const + { + bool q = !ns.empty (); + size_t h = hash (name.data (), name.size ()); + + if (q) + { + h = hash (h, " ", 1); + h = hash (h, ns.data (), ns.size ()); + } + + const bucket* p = find (h); + + if (p == 0) + return 0; + + // Search for the entry in the bucket. + // + const size_t el_size = sizeof (element) + sizeof (value); + const char* b = reinterpret_cast<const char*> (p) + sizeof (bucket); + const char* e = b + p->size_ * el_size; + + for (; b < e; b += el_size) + { + const element* e = reinterpret_cast<const element*> (b); + + if (e->hash_ == h) + { + if (!q) + { + if (strlen (e->key_) == name.size () && + strncmp (e->key_, name.data (), name.size ()) == 0) + break; + } + else + { + size_t n = name.size (); + + if (strncmp (e->key_, name.data (), n) == 0 && + e->key_[n] == ' ' && + strlen (e->key_ + n + 1) == ns.size () && + strncmp (e->key_ + n + 1, ns.data (), ns.size ()) == 0) + break; + } + } + } + + if (b == e) + return 0; + + return reinterpret_cast<const value*> (b + sizeof (element)); + } + + // substitution_map_init + // + substitution_map_init:: + substitution_map_init () + { + if (count == 0) + { + map = new substitution_map (XSDE_PARSER_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* member, + const char* root, + const char* type) + { + substitution_map& m = substitution_map_instance (); + m.insert (member, root, 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 + parser_smap_elements () + { + return substitution_map_instance ().size (); + } + } + } +} |