//////////////////////////////////////////////////////////////////////////////// // Author: Andy Rushton // Copyright: (c) Southampton University 1999-2004 // (c) Andy Rushton 2004-2009 // License: BSD License, see ../docs/license.html //////////////////////////////////////////////////////////////////////////////// #include "persistent_bool.hpp" #include "persistent_int.hpp" #include "persistent_xref.hpp" namespace stlplus { //////////////////////////////////////////////////////////////////////////////// template void dump_ntree_r(dump_context& context, const ntree& tree, const TYPENAME ntree::const_iterator& node, D dump_fn) throw(persistent_dump_failed) { // the magic key of the ntree_node is dumped as well as the contents - this is used in iterator persistence std::pair node_mapping = context.pointer_map(node.node()); if (node_mapping.first) throw persistent_dump_failed("ntree: already dumped this node"); dump_unsigned(context,node_mapping.second); // now dump the contents dump_fn(context,*node); // dump the number of children unsigned children = tree.children(node); dump_unsigned(context,children); // recurse on the children for (unsigned i = 0; i < children; i++) dump_ntree_r(context,tree,tree.child(node,i),dump_fn); } template void dump_ntree(dump_context& context, const ntree& tree, D dump_fn) throw(persistent_dump_failed) { // dump a magic key to the address of the tree for use in persistence of iterators // and register it as a dumped address std::pair mapping = context.pointer_map(&tree); if (mapping.first) throw persistent_dump_failed("ntree: already dumped this tree"); dump_unsigned(context,mapping.second); // now dump the tree contents - start with a flag to indicate whether the tree is empty dump_bool(context, tree.empty()); // now recursively dump the contents if (!tree.empty()) dump_ntree_r(context,tree,tree.root(),dump_fn); } //////////////////////////////////////////////////////////////////////////////// template void restore_ntree_r(restore_context& context, ntree& tree, const TYPENAME ntree::iterator& node, R restore_fn) throw(persistent_restore_failed) { // restore the node magic key, check whether it has been used before and add it to the set of known addresses unsigned node_magic = 0; restore_unsigned(context,node_magic); std::pair node_mapping = context.pointer_map(node_magic); if (node_mapping.first) throw persistent_restore_failed("ntree: restored this tree node already"); context.pointer_add(node_magic,node.node()); // now restore the node contents restore_fn(context,*node); // restore the number of children unsigned children = 0; restore_unsigned(context,children); // recurse on each child for (unsigned i = 0; i < children; i++) { typename ntree::iterator child = tree.insert(node,i,T()); restore_ntree_r(context,tree,child,restore_fn); } } template void restore_ntree(restore_context& context, ntree& tree, R restore_fn) throw(persistent_restore_failed) { tree.erase(); // restore the tree's magic key and map it onto the tree's address // this is used in the persistence of iterators unsigned magic = 0; restore_unsigned(context,magic); context.pointer_add(magic,&tree); // now restore the contents bool empty = true; restore_bool(context, empty); if (!empty) { typename ntree::iterator node = tree.insert(T()); restore_ntree_r(context,tree,node,restore_fn); } } //////////////////////////////////////////////////////////////////////////////// template void dump_ntree_iterator(dump_context& context, const ntree_iterator& data) throw(persistent_dump_failed) { data.assert_valid(); dump_xref(context,data.owner()); dump_xref(context,data.node()); } template void restore_ntree_iterator(restore_context& context, ntree_iterator& data) throw(persistent_restore_failed) { const ntree* owner = 0; ntree_node* node = 0; restore_xref(context,owner); restore_xref(context,node); data = ntree_iterator(node->m_master); data.assert_valid(owner); } //////////////////////////////////////////////////////////////////////////////// template void dump_ntree_prefix_iterator(dump_context& context, const ntree_prefix_iterator& data) throw(persistent_dump_failed) { dump_ntree_iterator(context,data.iterator()); } template void restore_ntree_prefix_iterator(restore_context& context, ntree_prefix_iterator& data) throw(persistent_restore_failed) { ntree_iterator iterator; restore_ntree_iterator(context,iterator); data = ntree_prefix_iterator(iterator); } //////////////////////////////////////////////////////////////////////////////// template void dump_ntree_postfix_iterator(dump_context& context, const ntree_postfix_iterator& data) throw(persistent_dump_failed) { dump_ntree_iterator(context,data.iterator()); } template void restore_ntree_postfix_iterator(restore_context& context, ntree_postfix_iterator& data) throw(persistent_restore_failed) { ntree_iterator iterator; restore_ntree_iterator(context,iterator); data = ntree_postfix_iterator(iterator); } //////////////////////////////////////////////////////////////////////////////// } // end namespace stlplus