glibmm r697 - in trunk: . glib/glibmm glib/src tests/glibmm_tree
- From: murrayc svn gnome org
- To: svn-commits-list gnome org
- Subject: glibmm r697 - in trunk: . glib/glibmm glib/src tests/glibmm_tree
- Date: Tue, 29 Jul 2008 09:03:09 +0000 (UTC)
Author: murrayc
Date: Tue Jul 29 09:03:09 2008
New Revision: 697
URL: http://svn.gnome.org/viewvc/glibmm?rev=697&view=rev
Log:
2008-07-29 SzilÃrd Pfeiffer <szilard pfeiffer gmail com>
* glib/src/tree.hg: Make the callbacks take a Tree<> instead of just
the data, so they can use methods on the tree (which can be a node
in the tree).
gobject_: Make this protected.
Provide the this pointer as data to g_node_new() so we can retrieve
it later.
Removed children_ and parent_ because we don't need a separate store now that
we can get the C++ instance from the gobject instance.
owns_gobject_: Removed because it is was always true, so the gobject was
always destroyed (and still is).
* tests/glibmm_tree/main.cc: Updated for the changed API.
Bug #520778.
Modified:
trunk/ChangeLog
trunk/glib/glibmm/objectbase.h
trunk/glib/src/tree.hg
trunk/tests/glibmm_tree/main.cc
Modified: trunk/glib/glibmm/objectbase.h
==============================================================================
--- trunk/glib/glibmm/objectbase.h (original)
+++ trunk/glib/glibmm/objectbase.h Tue Jul 29 09:03:09 2008
@@ -136,10 +136,10 @@
*/
virtual void unreference() const;
- ///Provides access to the underlying C GtkObject.
+ ///Provides access to the underlying C GObject.
inline GObject* gobj() { return gobject_; }
- ///Provides access to the underlying C GtkObject.
+ ///Provides access to the underlying C GObject.
inline const GObject* gobj() const { return gobject_; }
/// Give a ref-ed copy to someone. Use for direct struct access.
Modified: trunk/glib/src/tree.hg
==============================================================================
--- trunk/glib/src/tree.hg (original)
+++ trunk/glib/src/tree.hg Tue Jul 29 09:03:09 2008
@@ -43,7 +43,7 @@
*
* To reverse the children of a node use reverse_children().
*
- * To find a node use root(), find(), find_child(), index_of(), position_of(), first_child(), last_child(), nth_child(), first_sibling(), prev_sibling(), next_sibling() or last_sibling().
+ * To find a node use root(), find(), find_child(), index_of(), child_index(), first_child(), last_child(), nth_child(), first_sibling(), prev_sibling(), next_sibling() or last_sibling().
*
* To get information about a node or tree use is_leaf(), is_root(), depth(), node_count(), child_count(), is_ancestor() or max_height().
*
@@ -58,31 +58,24 @@
{
_CLASS_GENERIC(Tree, GNode)
public:
- typedef gpointer iterator;
- typedef sigc::slot<bool, T&>* TraverseFunc;
- typedef sigc::slot<void, T&>* ForeachFunc;
- typedef std::map<gpointer, Tree<T>*> NodeMap;
+ typedef sigc::slot<bool, Tree<T>&> TraverseFunc;
+ typedef sigc::slot<void, Tree<T>&> ForeachFunc;
- /** Creates a new Tree containing the given data.
- * Used to create the first node in a tree.
- */
- Tree()
- : gobject_ (0),
- owns_gobject_(false),
- parent_(this)
- {
- }
-
- explicit Tree(T& data)
+private:
+ static Tree<T>* wrap(GNode *node)
{
- T* tmp = new T();
- *tmp = data;
+ if (!node)
+ return 0;
- gobject_ = g_node_new(reinterpret_cast<gpointer>(tmp));
- owns_gobject_ = true;
- parent_ = this;
+ return reinterpret_cast<Tree<T> *>(node->data);
}
+public:
+ explicit Tree(T& data) :
+ data_(data)
+ {
+ gobject_ = g_node_new(reinterpret_cast<gpointer>(this));
+ };
_IGNORE(g_node_new)
/** Removes the instance and its children from the tree,
@@ -90,23 +83,8 @@
*/
~Tree()
{
- if(this != parent_)
- {
- parent_->unlink(*this);
- }
-
- for(typename NodeMap::iterator i = children_.begin();
- i != children_.end(); ++i)
- {
- delete i->second;
- }
-
- if(owns_gobject_)
- {
- delete reinterpret_cast<T*>(gobject_->data);
- g_node_destroy(gobject_);
- }
- }
+ g_node_destroy(gobj());
+ };
_IGNORE(g_node_destroy)
@@ -119,9 +97,7 @@
*/
Tree<T>& insert(int position, Tree<T>& node)
{
- children_[node.gobj()] = &node;
- g_node_insert(gobject_, position, node.gobj());
- node.parent(this);
+ g_node_insert(gobj(), position, node.gobj());
return node;
}
_IGNORE(g_node_insert)
@@ -134,9 +110,7 @@
*/
Tree<T>& insert_before(Tree<T>& sibling, Tree<T>& node)
{
- children_[node.gobj()] = &node;
- g_node_insert_before(gobject_, sibling.gobj(), node.gobj());
- node.parent(this);
+ g_node_insert_before(gobj(), sibling.gobj(), node.gobj());
return node;
}
_IGNORE(g_node_insert_before)
@@ -149,9 +123,7 @@
*/
Tree<T>& insert_after(Tree<T>& sibling, Tree<T>& node)
{
- children_[node.gobj()] = &node;
- g_node_insert_after(gobject_, sibling.gobj(), node.gobj());
- node.parent(this);
+ g_node_insert_after(gobj(), sibling.gobj(), node.gobj());
return node;
}
_IGNORE(g_node_insert_after)
@@ -164,9 +136,7 @@
*/
Tree<T>& append(Tree<T>& node)
{
- children_[node.gobj()] = &node;
- g_node_append(gobject_, node.gobj());
- node.parent(this);
+ g_node_append(gobj(), node.gobj());
return node;
}
_IGNORE(g_node_append)
@@ -178,9 +148,7 @@
*/
Tree<T>& prepend(Tree<T>& node)
{
- children_[node.gobj()] = &node;
- g_node_prepend(gobject_, node.gobj());
- node.parent(this);
+ g_node_prepend(gobj(), node.gobj());
return node;
}
_IGNORE(g_node_prepend)
@@ -244,7 +212,7 @@
*/
void reverse_children()
{
- g_node_reverse_children(gobject_);
+ g_node_reverse_children(gobj());
}
_IGNORE(g_node_reverse_children)
@@ -254,7 +222,7 @@
*/
Tree<T>* root() const
{
- return (this == parent_)? parent_: parent_->root();
+ return wrap(g_node_get_root(gobj()));
}
_IGNORE(g_node_get_root)
@@ -271,9 +239,10 @@
* If max_depth is 2, the root and its children are visited. And so on.
* @param func the slot to invoke for each visited child
*/
- void traverse(TraverseType order, TraverseFlags flags, int max_depth, TraverseFunc func)
+ void traverse(TraverseType order, TraverseFlags flags, int max_depth, const TraverseFunc &func)
{
- g_node_traverse(gobject_, (GTraverseType)order, (GTraverseFlags)flags, max_depth, wrap_traverse_slot, reinterpret_cast<gpointer>(func));
+ TraverseFunc func_copy = func;
+ g_node_traverse(gobj(), (GTraverseType)order, (GTraverseFlags)flags, max_depth, wrap_traverse_slot, reinterpret_cast<gpointer>(&func_copy));
}
_IGNORE(g_node_traverse);
@@ -283,9 +252,10 @@
* @param flags Wwhich types of children are to be visited: One of TRAVERSE_ALL, TRAVERSE_LEAVES and TRAVERSE_NON_LEAVES.
* @param func The slot to invoke for each visited node.
*/
- void foreach(TraverseFlags flags, ForeachFunc func)
+ void foreach(TraverseFlags flags, const ForeachFunc &func)
{
- g_node_children_foreach(gobject_, (GTraverseFlags)flags, wrap_foreach_slot, reinterpret_cast<gpointer>(func));
+ ForeachFunc func_copy = func;
+ g_node_children_foreach(gobj(), (GTraverseFlags)flags, wrap_foreach_slot, reinterpret_cast<gpointer>(&func_copy));
}
_IGNORE(g_node_children_foreach)
@@ -302,9 +272,9 @@
GNode* child = 0;
type_foreach_gnode_slot bound_slot = sigc::bind(real_slot, data, child);
- g_node_children_foreach(gobject_, (GTraverseFlags)flags, on_wrap_compare_child, reinterpret_cast<gpointer>(&bound_slot));
+ g_node_children_foreach(gobj(), (GTraverseFlags)flags, on_wrap_compare_child, reinterpret_cast<gpointer>(&bound_slot));
- return lookup(child);
+ return wrap(child);
}
_IGNORE(g_node_find_child)
@@ -319,34 +289,12 @@
{
//We use a sigc::slot for the C callback, so we can bind some extra data.
sigc::slot<gboolean, GNode*, const T&, GNode**> real_slot = sigc::ptr_fun(on_compare_node);
-
GNode* child = 0;
type_traverse_gnode_slot bound_slot = sigc::bind(real_slot, data, &child);
-
+
g_node_traverse(gobject_, (GTraverseType)order, (GTraverseFlags)flags, -1, on_wrap_compare_node, reinterpret_cast<gpointer>(&bound_slot));
- if(0 == child)
- return 0;
-
- GNode* cursor = child;
- unsigned int depth = g_node_depth(cursor) - g_node_depth(gobject_);
- std::stack<iterator, std::deque<iterator> > stack;
- Tree<T>* treecursor = const_cast<Tree<T>*>(this);
-
- for(unsigned int i = 0; i < depth; ++i)
- {
- stack.push(cursor);
- cursor = cursor->parent;
- }
-
- for(;!stack.empty();stack.pop())
- {
- treecursor = treecursor->lookup(stack.top());
- if(0 == treecursor)
- return 0;
- }
-
- return treecursor;
+ return wrap(child);
}
_IGNORE(g_node_find)
@@ -356,17 +304,18 @@
* @return The index of the child which contains data,
* or -1 if the data is not found.
*/
- int index_of(const T& data) const
+ int child_index(const T& data) const
{
- int index = 0;
- for(Tree<T>* i = nth_child(index);
- i != 0; i = nth_child(++index))
+ int n = 0;
+
+ for(Tree<T>* i = first_child();
+ i != 0; i = i->next_sibling())
{
if((i->data()) == data)
- {
- return index;
- }
+ return n;
+ n++;
}
+
return -1;
}
_IGNORE(g_node_child_index)
@@ -378,9 +327,9 @@
* @param child A child
* @return The position of @a child with respect to its siblings.
*/
- int position_of(const Tree<T>& child) const
+ int child_position(const Tree<T>& child) const
{
- return g_node_child_position(gobject_, const_cast<GNode*>(child.gobj()));
+ return g_node_child_position(gobj(), const_cast<GNode*>(child.gobj()));
}
_IGNORE(g_node_child_position)
@@ -390,7 +339,7 @@
*/
Tree<T>* first_child() const
{
- return lookup(g_node_first_child(gobject_));
+ return wrap(g_node_first_child(gobj()));
}
_IGNORE(g_node_first_child)
@@ -400,7 +349,7 @@
*/
Tree<T>* last_child() const
{
- return lookup(g_node_last_child(gobject_));
+ return wrap(g_node_last_child(gobj()));
}
_IGNORE(g_node_last_child)
@@ -410,16 +359,16 @@
*/
Tree<T>* nth_child(int n) const
{
- return lookup(g_node_nth_child(gobject_, n));
+ return wrap(g_node_nth_child(gobj(), n));
}
_IGNORE(g_node_nth_child)
-
+
/** Gets the first sibling
* @return The first sibling, or 0 if the node has no siblings.
*/
Tree<T>* first_sibling() const
{
- return parent_->lookup(g_node_first_sibling(gobject_));
+ return wrap(g_node_first_sibling(gobj()));
}
_IGNORE(g_node_first_sibling)
@@ -429,7 +378,7 @@
*/
Tree<T>* prev_sibling() const
{
- return parent_->lookup(g_node_prev_sibling(gobject_));
+ return wrap(g_node_prev_sibling(gobj()));
}
_IGNORE(g_node_prev_sibling)
@@ -439,7 +388,7 @@
*/
Tree<T>* next_sibling() const
{
- return parent_->lookup(g_node_next_sibling(gobject_));
+ return wrap(g_node_next_sibling(gobj()));
}
_IGNORE(g_node_next_sibling)
@@ -449,7 +398,7 @@
*/
Tree<T>* last_sibling() const
{
- return parent_->lookup(g_node_last_sibling(gobject_));
+ return wrap(g_node_last_sibling(gobj()));
}
_IGNORE(g_node_last_sibling)
@@ -459,7 +408,7 @@
*/
bool is_leaf() const
{
- return G_NODE_IS_LEAF(gobject_);
+ return G_NODE_IS_LEAF(gobj());
}
/** Returns true if this is the root node.
@@ -468,7 +417,7 @@
*/
bool is_root() const
{
- return G_NODE_IS_ROOT(gobject_);
+ return G_NODE_IS_ROOT(gobj());
}
/** Gets the depth of this node.
@@ -479,7 +428,7 @@
*/
unsigned int depth() const
{
- return g_node_depth(gobject_);
+ return g_node_depth(gobj());
}
_IGNORE(g_node_depth)
@@ -490,7 +439,7 @@
*/
unsigned int node_count(TraverseFlags flags) const
{
- return g_node_n_nodes(gobject_, (GTraverseFlags)flags);
+ return g_node_n_nodes(gobj(), (GTraverseFlags)flags);
}
_IGNORE(g_node_n_nodes)
@@ -500,7 +449,7 @@
*/
unsigned int child_count() const
{
- return g_node_n_children(gobject_);
+ return g_node_n_children(gobj());
}
_IGNORE(g_node_n_children)
@@ -513,7 +462,7 @@
*/
bool is_ancestor(const Tree<T>& descendant) const
{
- return g_node_is_ancestor(gobject_, const_cast<GNode*>(descendant.gobj()));
+ return g_node_is_ancestor(gobj(), const_cast<GNode*>(descendant.gobj()));
}
_IGNORE(g_node_is_ancestor)
@@ -525,7 +474,7 @@
*/
unsigned int max_height() const
{
- return g_node_max_height(gobject_);
+ return g_node_max_height(gobj());
}
_IGNORE(g_node_max_height)
@@ -533,77 +482,57 @@
*/
void unlink(Tree<T>& child)
{
- children_.erase(child.gobj());
- child.parent(&child);
g_node_unlink(child.gobj());
}
_IGNORE(g_node_unlink)
- /// Accessor for this node's iterator
- iterator iter() const
- {
- return gobject_;
- }
-
/// Accessor for this node's data
T& data() const
{
- return *(reinterpret_cast<T*>(gobject_->data));
+ return data_;
}
- /** Lookup a child by its iterator.
+ /** Accessor for this node's parent.
*
- * @param child The iterator of the desired child.
- * @return The child if found, else 0.
+ * @return The node's parent.
*/
- Tree<T>* lookup(const iterator child) const
+ const Tree<T>* parent() const
{
- typename NodeMap::const_iterator i = children_.find(child);
- return (children_.end() == i)? 0: i->second;
+ return wrap(gobj()->parent);
}
- // For auto-wrapping
- GNode* gobj() { return gobject_; }
- const GNode* gobj() const { return gobject_; }
+ /// For auto-wrapping
+ GNode* gobj() const
+ {
+ return gobject_;
+ }
// Leaving these unimplemented for now
_IGNORE(g_node_copy)
_IGNORE(g_node_copy_deep)
protected:
-
- /** Accessor for this node's parent.
- *
- * @param newparent Provides a new parent for this node. Use 0 to get the current parent.
- * @return The node's parent.
- */
- Tree<T>* parent(Tree<T> *newparent = 0)
- {
- return (0 == newparent) ? parent_: (parent_ = newparent);
- }
+ GNode *gobject_;
+ T &data_;
/// Wrapper for invoking a TraverseFunc.
static gboolean wrap_traverse_slot(GNode* node, gpointer slot)
{
- TraverseFunc tf = reinterpret_cast<TraverseFunc>(slot);
- if(tf)
- return ((*tf)(*(reinterpret_cast<T*>(node->data)))) ? TRUE : FALSE;
- else
- return FALSE;
+ const TraverseFunc* tf = reinterpret_cast<const TraverseFunc*>(slot);
+ return (*tf)(*wrap(node));
}
/// Wrapper for invoking a ForeachFunc.
static void wrap_foreach_slot(GNode* node, gpointer slot)
{
- ForeachFunc ff = reinterpret_cast<ForeachFunc>(slot);
- if(ff)
- (*ff)(*(reinterpret_cast<T*>(node->data)));
+ const ForeachFunc* ff = reinterpret_cast<const ForeachFunc*>(slot);
+ (*ff)(*wrap(node));
}
/// Method for comparing a single child (Internal use).
static void on_compare_child(GNode* node, const T& needle, GNode* result)
{
- if((0 != result) && ((*(reinterpret_cast<T*>(node->data))) == needle))
+ if((0 != result) && (wrap(node)->data() == needle))
{
result = node;
}
@@ -612,38 +541,30 @@
/// Wrapper for invoking a sigc::slot<void,GNode*> (Internal use).
static void on_wrap_compare_child(GNode* node, gpointer data)
{
- type_foreach_gnode_slot* slot = reinterpret_cast<type_foreach_gnode_slot*>(data);
- (*slot)(node);
+ const ForeachFunc *slot = reinterpret_cast<const ForeachFunc *>(data);
+ (*slot)(*wrap(node));
}
/// Method for comparing a single node (Internal use).
static gboolean on_compare_node(GNode* node, const T& needle, GNode** result)
{
- if((*(reinterpret_cast<T*>(node->data))) == needle)
+ if(wrap(node)->data() == needle)
{
*result = node;
return TRUE;
}
-
return FALSE;
}
/// Wrapper for invoking a sigc::slot<gboolean,GNode*> (Internal use).
static gboolean on_wrap_compare_node(GNode* node, gpointer data)
{
- type_traverse_gnode_slot* slot = reinterpret_cast<type_traverse_gnode_slot*>(data);
- return (*slot)(node);
+ const TraverseFunc *slot = reinterpret_cast<const TraverseFunc *>(data);
+ return (*slot)(*wrap(node));
}
typedef sigc::slot<gboolean, GNode*> type_traverse_gnode_slot;
typedef sigc::slot<void, GNode*> type_foreach_gnode_slot;
-
- GNode* gobject_;
- bool owns_gobject_;
-
- // Some metadata must be stored.
- NodeMap children_;
- Tree<T>* parent_;
};
} // namespace Glib
Modified: trunk/tests/glibmm_tree/main.cc
==============================================================================
--- trunk/tests/glibmm_tree/main.cc (original)
+++ trunk/tests/glibmm_tree/main.cc Tue Jul 29 09:03:09 2008
@@ -2,15 +2,16 @@
#include <glibmm.h>
-bool echo(std::string& i)
+bool echo(Glib::Tree<std::string>& i)
{
- std::cout << i << ' ';
+ std::cout << i.data() << ' ';
return false;
}
-void echof(std::string& i)
+void echol(Glib::Tree<std::string>& i, bool is_leaf)
{
- std::cout << i << ' ';
+ if(i.is_leaf() == is_leaf)
+ std::cout << i.data() << ' ';
}
@@ -28,8 +29,7 @@
tc(c),
te(e);
- sigc::slot<bool, std::string&> echoslot = sigc::ptr_fun(echo);
- sigc::slot<void, std::string&>echofslot = sigc::ptr_fun(echof);
+ sigc::slot<bool, Glib::Tree<std::string>&> echoslot = sigc::ptr_fun(echo);
ta.insert(0, tc);
@@ -39,19 +39,27 @@
te.prepend_data(f);
std::cout << "Breadth-first:" << std::endl;
- ta.traverse(Glib::LEVEL_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, &echoslot);
+ ta.traverse(Glib::LEVEL_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, echoslot);
std::cout << std::endl;
std::cout << "Depth-first (pre):" << std::endl;
- ta.traverse(Glib::PRE_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, &echoslot);
+ ta.traverse(Glib::PRE_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, echoslot);
std::cout << std::endl;
std::cout << "Depth-first (in):" << std::endl;
- ta.traverse(Glib::IN_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, &echoslot);
+ ta.traverse(Glib::IN_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, echoslot);
std::cout << std::endl;
std::cout << "Depth-first (post):" << std::endl;
- ta.traverse(Glib::POST_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, &echoslot);
+ ta.traverse(Glib::POST_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, INT_MAX, echoslot);
+ std::cout << std::endl;
+
+ std::cout << "Leaf children of 'a':" << std::endl;
+ ta.foreach(Glib::TRAVERSE_ALL, sigc::bind<bool>(sigc::ptr_fun(echol), true));
+ std::cout << std::endl;
+
+ std::cout << "Non-leaf children of 'a':" << std::endl;
+ ta.foreach(Glib::TRAVERSE_ALL, sigc::bind<bool>(sigc::ptr_fun(echol), false));
std::cout << std::endl;
Glib::Tree<std::string> *tmp = ta.find(Glib::IN_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, e);
@@ -62,13 +70,17 @@
if(NULL == tmp){ std::cout << a << " not found" << std::endl; }
else{ std::cout << "Found " << (tmp->data()) << std::endl; }
+ tmp = ta.find(Glib::IN_ORDER, Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, "f");
+ if(NULL == tmp){ std::cout << a << " not found" << std::endl; }
+ else{ std::cout << "Found " << (tmp->data()) << std::endl; }
+
tmp = ta.find_child(Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, e);
if(NULL == tmp){ std::cout << e << " is not a child of " << (ta.data()) << std::endl; }
else{ std::cout << "Mistakenly found " << e << " in " << (ta.data()) << "'s children" << std::endl; }
tmp = ta.find_child(Glib::TRAVERSE_LEAVES | Glib::TRAVERSE_NON_LEAVES, c);
if(NULL == tmp) {
- std::cout << c << " is the number " << ta.index_of(c) << " child of " << (ta.data()) << std::endl;
+ std::cout << c << " is the number " << ta.child_index(c) << " child of " << (ta.data()) << std::endl;
}
else{ std::cout << "Mistakenly didn't find " << c << " in " << (ta.data()) << "'s children" << std::endl; }
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]