Commit 45d4e675 authored by Vivien Kraus's avatar Vivien Kraus

Merge branch '32-have-a-generic-tree-structure' into 'develop'

Resolve "Have a generic tree structure"

Closes #32

See merge request gugurumbe/tarot!30
parents f2e5e75f 0b30b11b
Pipeline #104863 passed with stages
in 5 minutes
......@@ -33,7 +33,6 @@
#include <tarot/cli.h>
#include <tarot/xml.h>
#include <tarot/layout.h>
#include <tarot/tree.h>
#include <tarot/mcts.h>
#ifdef __cplusplus
......
......@@ -31,7 +31,6 @@ lib_LTLIBRARIES += %reldir%/libtarot.la
%reldir%/cli/libtarot-cli.la \
%reldir%/xml/libtarot-xml.la \
%reldir%/layout/libtarot-layout.la \
%reldir%/tree/libtarot-tree.la \
%reldir%/mcts/libtarot-mcts.la \
lib-library/libgnulibrary.la
......
......@@ -24,7 +24,9 @@ tarotinclude_HEADERS += %reldir%/tarot/mcts.h
%reldir%/mcts.c \
%reldir%/tarot/mcts.h \
%reldir%/tarot/mcts_private.h \
%reldir%/tarot/mcts_private_impl.h
%reldir%/tarot/mcts_private_impl.h \
%reldir%/tarot/mcts_tree_private.h \
%reldir%/tarot/mcts_tree_private_impl.h
%canon_reldir%_libtarot_mcts_la_CFLAGS = \
$(AM_CFLAGS) $(NETTLE_CFLAGS)
%canon_reldir%_libtarot_mcts_la_LDFLAGS = \
......@@ -34,3 +36,19 @@ INDENTED += $(%canon_reldir%_libtarot_mcts_la_SOURCES)
ENUM_HEADER_FILES += %reldir%/tarot/mcts.h
INTROSPECTED_SOURCES += %reldir%/mcts.c
$(srcdir)/%reldir%/tarot/mcts_tree_private.h: %reldir%/../tree/gentree-header.tpl %reldir%/node-tree.def
$(AM_V_GEN) $(AUTOGEN) -T $(srcdir)/%reldir%/../tree/gentree-header.tpl $(srcdir)/%reldir%/node-tree.def > $(srcdir)/%reldir%/tarot/mcts_tree_private.h
$(srcdir)/%reldir%/tarot/mcts_tree_private_impl.h: %reldir%/../tree/gentree-code.tpl %reldir%/node-tree.def
$(AM_V_GEN) $(AUTOGEN) -T $(srcdir)/%reldir%/../tree/gentree-code.tpl $(srcdir)/%reldir%/node-tree.def > $(srcdir)/%reldir%/tarot/mcts_tree_private_impl.h
$(srcdir)/%reldir%/tarot/mcts_private_impl.h: %reldir%/tarot/mcts_tree_private.h %reldir%/tarot/mcts_tree_private_impl.h
$(srcdir)/src/Tarot-@LIBTOOL_CURRENT@.0.gir: %reldir%/tarot/mcts_private_impl.h
EXTRA_DIST += \
%reldir%/tarot/mcts_tree_private.h \
%reldir%/tarot/mcts_tree_private_impl.h \
%reldir%/node-tree.def
MAINTAINERCLEANFILES += \
%reldir%/tarot/mcts_tree_private.h \
%reldir%/tarot/mcts_tree_private_impl.h
autogen definitions treegen;
header-guard = "H_TAROT_MCTS_TREE_INCLUDED";
type = {
declaration = "struct TarotMctsNode";
struct-name = "TarotMctsTree";
scope = "static";
name = "struct TarotMctsNode";
prefix = "tarot_mcts_tree";
implementation-code = "#include <config.h>";
implementation-code = "#include \"mcts_private.h\"";
};
\ No newline at end of file
......@@ -21,12 +21,13 @@
#define H_TAROT_MCTS_PRIVATE_INCLUDED
#include <tarot/mcts.h>
#include <tarot/game_event.h>
#include <tarot/tree.h>
#include <nettle/yarrow.h>
#include <tarot/game.h>
#include <tarot/counter.h>
#include <stdlib.h>
#include <assert.h>
#include <tarot/mcts_tree_private.h>
#ifdef __cplusplus
extern "C"
{
......@@ -44,10 +45,7 @@ extern "C"
struct TarotMcts
{
const TarotGame *base;
TarotTree *tree;
size_t n_nodes;
size_t max_nodes;
TarotMctsNode *nodes;
TarotMctsTree *tree;
};
static TarotMcts *mcts_alloc ();
......@@ -58,21 +56,21 @@ extern "C"
size_t seed_size, const void *seed);
static int mcts_get_best (const TarotMcts * mcts, TarotGameEvent * event);
static TarotMctsNode *mcts_alloc_node (TarotMcts * mcts);
static TarotTreeIndex mcts_select (const TarotMcts * mcts,
size_t n_iterations);
static int mcts_load (const TarotMcts * mcts, TarotTreeIndex leaf,
static TarotMctsTreeIterator mcts_select (const TarotMcts * mcts,
size_t n_iterations);
static int mcts_load (const TarotMcts * mcts, TarotMctsTreeIterator leaf,
TarotGame * game);
static int mcts_impute (TarotGame * game, struct yarrow256_ctx *rng);
static int mcts_next_move (const TarotGame * game, TarotGameEvent * event,
struct yarrow256_ctx *rng);
static int mcts_expand (TarotMcts * mcts, TarotTreeIndex * node,
static int mcts_expand (TarotMcts * mcts, TarotMctsTreeIterator * node,
TarotGameEvent * event, TarotPlayer myself);
/* local_event is just an allocated event */
static int mcts_simulate (struct yarrow256_ctx *rng, TarotGame * game,
TarotGameEvent * local_event, size_t n_players,
int *score);
static void mcts_backpropagate (TarotMcts * mcts, TarotTreeIndex node,
static void mcts_backpropagate (TarotMcts * mcts,
TarotMctsTreeIterator node,
size_t n_players, const int *score);
#ifdef __cplusplus
}
......
This diff is collapsed.
......@@ -61,7 +61,6 @@ TAROT_BOXED_TYPE (Lexer, lexer)
TAROT_BOXED_TYPE (Mcts, mcts)
TAROT_BOXED_TYPE (Parser, parser)
TAROT_BOXED_TYPE (PlayerArray, player_array)
TAROT_BOXED_TYPE (Tree, tree)
/*** END file-header ***/
/*** BEGIN file-production ***/
......
......@@ -41,7 +41,6 @@ extern "C"
GType tarot_mcts_get_type ();
GType tarot_parser_get_type ();
GType tarot_player_array_get_type ();
GType tarot_tree_get_type ();
/* *INDENT-OFF* */
/*** END file-header ***/
......
......@@ -16,41 +16,4 @@
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
noinst_LTLIBRARIES += %reldir%/libtarot-tree.la
tarotinclude_HEADERS += %reldir%/tarot/tree.h
%canon_reldir%_libtarot_tree_la_SOURCES = \
%reldir%/tree.c \
%reldir%/tarot/tree_private.h \
%reldir%/tarot/tree_private_impl.h
%canon_reldir%_libtarot_tree_la_LDFLAGS = \
-no-undefined $(AM_LDADD)
if WITH_GOBJECT
check_PROGRAMS += %reldir%/check-tree
%canon_reldir%_check_tree_SOURCES = \
%reldir%/tree_test.vala \
src/tarot-@LIBTOOL_CURRENT@.0.vapi
%canon_reldir%_check_tree_CFLAGS = \
$(AM_CFLAGS) \
$(LIBOPTS_CFLAGS) \
$(GOBJECT_CFLAGS) \
-w
%canon_reldir%_check_tree_CPPFLAGS = \
$(AM_CPPFLAGS) \
-include config.h
%canon_reldir%_check_tree_LDADD = \
src/libtarot.la \
src/libtarot-gobject.la \
lib-program/libgnuprogram.la \
$(LIBOPTS_LDADD) \
$(GOBJECT_LIBS)
INDENTED += $(%canon_reldir%_check_tree_SOURCES)
endif # WITH_GOBJECT
AM_CPPFLAGS += -I $(srcdir)/%reldir% -I %reldir%
INDENTED += $(%canon_reldir%_libtarot_tree_la_SOURCES)
INTROSPECTED_SOURCES += %reldir%/tree.c
EXTRA_DIST += %reldir%/gentree-header.tpl %reldir%/gentree-code.tpl
[+ AutoGen5 template +]
/**
* file gentree-code.tpl Generate code for generic trees.
*
* Copyright (C) 2019 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
[+ FOR implementation-code +]
[+ implementation-code +]
[+ ENDFOR +]
#include <string.h>
#ifndef TREE_NULL
#define TREE_NULL ((size_t) (-1))
#endif
[+ FOR type +]
struct GenTreeNode[+ struct-name +]
{
[+ struct-name +]Iterator up;
[+ struct-name +]Iterator left;
[+ struct-name +]Iterator right;
[+ name +] payload;
};
typedef struct GenTreeNode[+ struct-name +] GenTreeNode[+ struct-name +];
struct [+ struct-name +]
{
size_t max_nodes;
size_t n_nodes;
struct GenTreeNode[+ struct-name +] *data;
};
[+ scope +] struct [+ struct-name +] *
[+ prefix +]_alloc ()
{
struct [+ struct-name +] *ret = malloc (sizeof ([+struct-name +]));
if (ret != NULL)
{
ret->max_nodes = 1;
ret->n_nodes = 1;
ret->data = malloc (1 * sizeof (struct GenTreeNode[+ struct-name +]));
if (ret->data == NULL)
{
free (ret);
ret = NULL;
}
else
{
ret->data[0].up = TREE_NULL;
ret->data[0].left = TREE_NULL;
ret->data[0].right = TREE_NULL;
}
}
return ret;
}
[+ scope +] void
[+ prefix +]_free (struct [+ struct-name +] *tree)
{
if (tree != NULL)
{
free (tree->data);
}
free (tree);
}
[+ scope +] int
[+ prefix +]_copy (struct [+ struct-name +] *tree, const struct [+ struct-name +] *source)
{
size_t new_max_nodes = source->max_nodes;
GenTreeNode[+ struct-name +] *new_data = realloc (tree->data, new_max_nodes * sizeof (GenTreeNode[+ struct-name +]));
if (new_data == NULL)
{
return 1;
}
tree->max_nodes = new_max_nodes;
tree->n_nodes = source->n_nodes;
tree->data = new_data;
memcpy (tree->data, source->data, source->n_nodes * sizeof (GenTreeNode[+ struct-name +]));
return 0;
}
[+ scope +] struct [+ struct-name +] *
[+ prefix +]_dup (const struct [+ struct-name +] *tree)
{
struct [+ struct-name +] *ret = [+ prefix +]_alloc ();
if (ret != NULL)
{
if ([+ prefix +]_copy (ret, tree) != 0)
{
[+ prefix +]_free (ret);
ret = NULL;
}
}
return ret;
}
[+ scope +] [+ name +] *
[+ prefix +]_get (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return ([+ name +] *) & (tree->data[node].payload);
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_left (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return tree->data[node].left;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_right (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return tree->data[node].right;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_up (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return tree->data[node].up;
}
static int
gentree_[+ prefix +]_large_enough (struct [+ struct-name +] *tree)
{
if (tree->n_nodes > tree->max_nodes)
{
size_t new_max = 2 * tree->max_nodes;
GenTreeNode[+ struct-name +] *new_data = realloc (tree->data, new_max * sizeof (GenTreeNode[+ struct-name +]));
if (new_data == NULL)
{
return 1;
}
tree->max_nodes = new_max;
tree->data = new_data;
assert (tree->n_nodes <= tree->max_nodes);
}
return 0;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_insert_left (struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
[+ struct-name +]Iterator ret;
if (tree->data[node].left != TREE_NULL)
{
return TREE_NULL;
}
ret = (tree->n_nodes)++;
if (gentree_[+ prefix +]_large_enough (tree) != 0)
{
(tree->n_nodes)--;
return TREE_NULL;
}
tree->data[ret].up = node;
tree->data[ret].left = TREE_NULL;
tree->data[ret].right = TREE_NULL;
tree->data[node].left = ret;
return ret;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_insert_right (struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
[+ struct-name +]Iterator ret;
if (tree->data[node].right != TREE_NULL)
{
return TREE_NULL;
}
ret = (tree->n_nodes)++;
if (gentree_[+ prefix +]_large_enough (tree) != 0)
{
(tree->n_nodes)--;
return TREE_NULL;
}
tree->data[ret].up = node;
tree->data[ret].left = TREE_NULL;
tree->data[ret].right = TREE_NULL;
tree->data[node].right = ret;
return ret;
}
static void gentree_[+ prefix +]_replace_in_parent (struct [+ struct-name +] *tree, [+ struct-name +]Iterator old_node, [+ struct-name +]Iterator new_node)
{
if (tree->data[tree->data[old_node].up].left == old_node)
{
tree->data[tree->data[old_node].up].left = new_node;
}
else if (tree->data[tree->data[old_node].up].right == old_node)
{
tree->data[tree->data[old_node].up].right = new_node;
}
else
{
/* Inconsistent node: its parent does not know it. */
assert (0);
}
}
[+ scope +] void
[+ prefix +]_prune (struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
if (node != TREE_ROOT)
{
/* DANGEROUS: we swap node with tree->n_nodes - 1, and copy the
payload too! The last iterator will be invalidated, and the
payload will have to be reloaded because it does not live
there anymore */
(tree->n_nodes)--;
gentree_[+ prefix +]_replace_in_parent (tree, node, tree->n_nodes);
gentree_[+ prefix +]_replace_in_parent (tree, tree->n_nodes, node);
tree->data[node] = tree->data[tree->n_nodes];
tree->data[tree->data[node].left].up = node;
tree->data[tree->data[node].right].up = node;
}
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_first_child (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return tree->data[node].left;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_parent (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
while (node != TREE_ROOT && tree->data[tree->data[node].up].left != node)
{
node = tree->data[node].up;
}
if (node == TREE_ROOT)
{
assert (tree->data[node].up == TREE_NULL);
}
return tree->data[node].up;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_previous_sibling (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
if (node != TREE_ROOT && tree->data[tree->data[node].up].right == node)
{
return tree->data[node].up;
}
return TREE_NULL;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_next_sibling (const struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
return tree->data[node].right;
}
[+ scope +] [+ struct-name +]Iterator
[+ prefix +]_add_child (struct [+ struct-name +] *tree, [+ struct-name +]Iterator node)
{
if (tree->data[node].left == TREE_NULL)
{
return [+ prefix +]_insert_left (tree, node);
}
node = tree->data[node].left;
while (tree->data[node].right != TREE_NULL)
{
node = tree->data[node].right;
}
return [+ prefix +]_insert_right (tree, node);
}
[+ ENDFOR +]
/* Local Variables: */
/* mode: c */
/* End: */
[+ AutoGen5 template +]
/**
* file gentree-header.tpl Generate code for generic trees.
*
* Copyright (C) 2019 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
/* Don't forget to define header-guard in your autogen def file */
#ifndef [+ header-guard +]
#define [+ header-guard +]
#include <stddef.h>
[+ FOR header-code +]
[+ header-code +]
[+ ENDFOR +]
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef TREE_NULL
#define TREE_NULL ((size_t) (-1))
#endif
#ifndef TREE_ROOT
#define TREE_ROOT ((size_t) 0)
#endif
[+ FOR type +]
[+ declaration +];
struct [+ struct-name +];
typedef struct [+ struct-name +] [+ struct-name +];
typedef size_t [+ struct-name +]Iterator;
[+ scope +] [+ struct-name +] * [+ prefix +]_alloc ();
[+ scope +] void [+ prefix +]_free ([+ struct-name +] *tree);
[+ scope +] int [+ prefix +]_copy ([+ struct-name +] *tree, const [+ struct-name +] *source);
[+ scope +] [+ struct-name +] * [+ prefix +]_dup (const [+ struct-name +] *tree);
[+ scope +] [+ name +] * [+ prefix +]_get (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_left (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_right (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_up (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_insert_left ([+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_insert_right ([+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] void [+ prefix +]_prune ([+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_first_child (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_parent (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_previous_sibling (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_next_sibling (const [+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ scope +] [+ struct-name +]Iterator [+ prefix +]_add_child ([+ struct-name +] *tree, [+ struct-name +]Iterator node);
[+ ENDFOR +]
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* not [+ header-guard +] */
/* Local Variables: */
/* mode: c */
/* End: */
/**
* file tree.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef H_TAROT_TREE_INCLUDED
#define H_TAROT_TREE_INCLUDED
#include <stddef.h>
#include <tarot/player.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* The first half of the interface is for binary trees.
*/
struct TarotTree;
typedef struct TarotTree TarotTree;
typedef size_t TarotTreeIndex;
/**
* tarot_tree_alloc: (constructor):
*/
TarotTree *tarot_tree_alloc ();
/**
* tarot_tree_free: (skip):
*/
void tarot_tree_free (TarotTree * tree);
int tarot_tree_copy (TarotTree * dest, const TarotTree * source);
/**
* tarot_tree_dup: (skip):
*/
TarotTree *tarot_tree_dup (const TarotTree * source);
TarotTreeIndex tarot_tree_root (const TarotTree * tree);
void *tarot_tree_get (const TarotTree * tree, TarotTreeIndex node);
/**
* tarot_tree_is_valid:
* Returns: (type boolean):
*/
int tarot_tree_is_valid (const TarotTree * tree, TarotTreeIndex node);
TarotTreeIndex tarot_tree_left (const TarotTree * tree,
TarotTreeIndex node);
TarotTreeIndex tarot_tree_right (const TarotTree * tree,
TarotTreeIndex node);
TarotTreeIndex tarot_tree_up (const TarotTree * tree, TarotTreeIndex node);
void tarot_tree_set (TarotTree * tree, TarotTreeIndex node, void *data);
int tarot_tree_insert_left (TarotTree * tree, TarotTreeIndex root);
int tarot_tree_insert_right (TarotTree * tree, TarotTreeIndex root);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* not H_TAROT_TREE_INCLUDED */
/* Local Variables: */
/* mode: c */
/* End: */
/**
* file tree_private.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef H_TAROT_TREE_PRIVATE_INCLUDED
#define H_TAROT_TREE_PRIVATE_INCLUDED
#include <stddef.h>
#include <tarot/tree.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
typedef struct TarotTreeNode TarotTreeNode;
struct TarotTreeNode
{
void *data;
TarotTreeIndex parent;
TarotTreeIndex left;
TarotTreeIndex right;
};
struct TarotTree
{
size_t n_nodes;
size_t max_nodes;
TarotTreeNode *nodes;
};
static TarotTree *tree_alloc ();
static void tree_free (TarotTree * tree);
static int tree_copy (TarotTree * dest, const TarotTree * source);
static TarotTree *tree_dup (const TarotTree * source);
static TarotTreeIndex tree_root (const TarotTree * source);
static void *tree_get (const TarotTree * tree, TarotTreeIndex node);
static int tree_is_valid (const TarotTree * tree, TarotTreeIndex node);
static TarotTreeIndex tree_left (const TarotTree * tree,
TarotTreeIndex node);
static TarotTreeIndex tree_right (const TarotTree * tree,
TarotTreeIndex node);
static TarotTreeIndex tree_up (const TarotTree * tree, TarotTreeIndex node);
static void tree_set (TarotTree * tree, TarotTreeIndex node, void *data);
static int tree_insert_left (TarotTree * tree, TarotTreeIndex root);
static int tree_insert_right (TarotTree * tree, TarotTreeIndex root);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* not H_TAROT_TREE_PRIVATE_INCLUDED */
/* Local Variables: */
/* mode: c */
/* End: */
/**
* file tree_private_impl.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
static inline TarotTree *
tree_alloc ()
{
TarotTree *ret = malloc (sizeof (TarotTree));
if (ret != NULL)
{
ret->n_nodes = 1;
ret->max_nodes = 1;
ret->nodes = malloc (sizeof (TarotTreeNode));
if (ret->nodes == NULL)
{
free (ret);
ret = NULL;
}
else
{
ret->nodes[0].parent = (size_t) (-1);
ret->nodes[0].left = (size_t) (-1);
ret->nodes[0].right = (size_t) (-1);
}
}
return ret;
}
static inline void
tree_free (TarotTree * tree)
{
if (tree != NULL)
{
free (tree->nodes);
}
free (tree);
}
static inline int
tree_copy (TarotTree * dest, const TarotTree * source)
{
TarotTreeNode *new_nodes =
realloc (dest->nodes, source->max_nodes * sizeof (TarotTreeNode));
if (new_nodes == NULL)
{