aboutsummaryrefslogtreecommitdiff
path: root/libxsde/xsde/cxx/serializer
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-10-18 11:17:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-10-18 11:17:51 +0200
commitd80d096ee8743fd6f7382d274272b0b6d7faf9bf (patch)
treed0f0bee1e645cb2b86b6837ac0db8a7d2821e533 /libxsde/xsde/cxx/serializer
parent0e4637025fa8d1b4234b0512561d31f0dd023843 (diff)
Support for schema evolution using substitution groups
New examples: hybrid/evolution/ignore and hybrid/evolution/passthrough.
Diffstat (limited to 'libxsde/xsde/cxx/serializer')
-rw-r--r--libxsde/xsde/cxx/serializer/genx/document.cxx2
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map-callback.hxx26
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.cxx133
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.hxx23
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.ixx13
5 files changed, 136 insertions, 61 deletions
diff --git a/libxsde/xsde/cxx/serializer/genx/document.cxx b/libxsde/xsde/cxx/serializer/genx/document.cxx
index 4c634a4..e8cacc0 100644
--- a/libxsde/xsde/cxx/serializer/genx/document.cxx
+++ b/libxsde/xsde/cxx/serializer/genx/document.cxx
@@ -514,7 +514,7 @@ namespace xsde
// Call to check sets ns and n if successful.
//
if (strcmp (dt, root_static_type_) == 0 ||
- substitution_map_instance ().check (ns, n, dt))
+ substitution_map_instance ().check (ns, n, dt, 0))
dt = 0;
}
diff --git a/libxsde/xsde/cxx/serializer/substitution-map-callback.hxx b/libxsde/xsde/cxx/serializer/substitution-map-callback.hxx
new file mode 100644
index 0000000..c29a00d
--- /dev/null
+++ b/libxsde/xsde/cxx/serializer/substitution-map-callback.hxx
@@ -0,0 +1,26 @@
+// file : xsde/cxx/serializer/substitution-map-callback.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_CALLBACK_HXX
+#define XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_CALLBACK_HXX
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ void
+ serializer_smap_callback (
+ bool (*callback) (
+ const char* type,
+ const void* obj,
+ const char*& ns,
+ const char*& name));
+ }
+ }
+}
+
+#endif // XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_CALLBACK_HXX
diff --git a/libxsde/xsde/cxx/serializer/substitution-map.cxx b/libxsde/xsde/cxx/serializer/substitution-map.cxx
index 28f01b5..dc73fd2 100644
--- a/libxsde/xsde/cxx/serializer/substitution-map.cxx
+++ b/libxsde/xsde/cxx/serializer/substitution-map.cxx
@@ -17,6 +17,7 @@
#endif
#include <xsde/cxx/serializer/substitution-map.hxx>
+#include <xsde/cxx/serializer/substitution-map-callback.hxx>
#include <xsde/cxx/serializer/substitution-map-load.hxx>
namespace xsde
@@ -103,8 +104,19 @@ namespace xsde
bool substitution_map::
check_ (const char*& ns,
const char*& name,
- const char* type) const
+ const char* type,
+ const void* obj,
+ bool top) const
{
+ // Call the callback first to allow the user to provide a custom
+ // substitution group mapping.
+ //
+ if (top && callback_ != 0)
+ {
+ if (callback_ (type, obj, ns, name))
+ return true;
+ }
+
size_t h = hash (name);
if (ns)
@@ -115,70 +127,70 @@ namespace xsde
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)
+ if (p != 0)
{
- const element* e = reinterpret_cast<const element*> (b);
+ // 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;
- if (e->hash_ == h)
+ for (; b < e; b += el_size)
{
- if (ns == 0)
- {
- if (strcmp (e->key_, name) == 0)
- break;
- }
- else
+ const element* e = reinterpret_cast<const element*> (b);
+
+ if (e->hash_ == h)
{
- if (strncmp (e->key_, name, nl) == 0 &&
- e->key_[nl] == ' ' &&
- strcmp (e->key_ + nl + 1, ns) == 0)
- break;
+ 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));
+ if (b != e)
+ {
+ 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;
- }
+ // 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);
+ // 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_;
+ const char* tns = v->ns_;
+ const char* tn = v->name_;
- if (check_ (tns, tn, type))
- {
- ns = tns;
- name = tn;
- return true;
+ if (check_ (tns, tn, type, obj, false))
+ {
+ ns = tns;
+ name = tn;
+ return true;
+ }
+ }
}
}
@@ -264,7 +276,20 @@ namespace xsde
#endif
}
+ // Callback.
//
+ void
+ serializer_smap_callback (
+ bool (*callback) (
+ const char* type,
+ const void* obj,
+ const char*& ns,
+ const char*& name))
+ {
+ substitution_map_instance ().callback (callback);
+ }
+
+ // Load.
//
size_t
serializer_smap_elements ()
diff --git a/libxsde/xsde/cxx/serializer/substitution-map.hxx b/libxsde/xsde/cxx/serializer/substitution-map.hxx
index ae16f4c..e36c481 100644
--- a/libxsde/xsde/cxx/serializer/substitution-map.hxx
+++ b/libxsde/xsde/cxx/serializer/substitution-map.hxx
@@ -30,21 +30,34 @@ namespace xsde
const char* member_name,
const char* member_type);
+ typedef bool (*callback_func) (
+ const char* type,
+ const void* obj,
+ const char*& ns,
+ const char*& name);
+
+ void
+ callback (callback_func);
+
// Check whether there is a substitution available for this
// root element with the specified type. If so, return true
// and override namespace and name (ns is 0 if there is no
- // namespace).
+ // namespace). The obj argument is an opaque pointer to the
+ // instance being serialized or 0 if there is none.
//
bool
check (const char*& ns,
const char*& name,
- const char* type) const;
+ const char* type,
+ const void* obj) const;
private:
bool
check_ (const char*& ns,
const char*& name,
- const char* type) const;
+ const char* type,
+ const void* obj,
+ bool top) const;
private:
struct value
@@ -52,6 +65,9 @@ namespace xsde
const char* ns_;
const char* name_;
};
+
+ private:
+ callback_func callback_;
};
@@ -85,4 +101,3 @@ namespace xsde
#include <xsde/cxx/serializer/substitution-map.ixx>
#endif // XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_HXX
-
diff --git a/libxsde/xsde/cxx/serializer/substitution-map.ixx b/libxsde/xsde/cxx/serializer/substitution-map.ixx
index 6622e33..6dbd951 100644
--- a/libxsde/xsde/cxx/serializer/substitution-map.ixx
+++ b/libxsde/xsde/cxx/serializer/substitution-map.ixx
@@ -15,12 +15,21 @@ namespace xsde
{
}
+ inline void substitution_map::
+ callback (callback_func c)
+ {
+ callback_ = c;
+ }
+
inline bool substitution_map::
check (const char*& ns,
const char*& name,
- const char* type) const
+ const char* type,
+ const void* obj) const
{
- return empty () ? false : check_ (ns, name, type);
+ return !empty () || callback_ != 0
+ ? check_ (ns, name, type, obj, true)
+ : false;
}
inline substitution_map&