/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file gpl.txt included in the packaging
 * of this file.  (See http://www.gnu.org/licenses/translations.html for
 * unofficial translations.)
 * 
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

#include <bp/common.h>
#include "bst.h"

void bst_create(struct bst *t, struct marena *arena)
{
   t->root = NULL;
   if (arena) {
      t->arena = arena;
      t->private_arena = false;
   } else {
      t->arena = bp_malloc(sizeof *t->arena);
      marena_create(t->arena);
      t->private_arena = true;
   }
}

void bst_empty(struct bst *t)
{
   t->root = NULL;
   marena_release(t->arena);
}

void bst_destroy(struct bst *t)
{
   t->root = NULL;
   if (t->private_arena) {
      marena_destroy(t->arena);
      free(t->arena);
   }
}

static struct bst_node *bst_search(struct bst_node *t, uint32_t val,
   struct bst_node **last)
{
   *last = NULL;
   while (t && t->val != val) {
      *last = t;
      if (val < t->val)
         t = t->left;
      else
         t = t->right;
   };
   return t;
}

void bst_insert(struct bst *t, uint32_t val)
{
   struct bst_node *newnode, *parent;
   if (bst_search(t->root, val, &parent))
      return;
   newnode = bp_marena_alloc(t->arena, sizeof *newnode);
   newnode->left = newnode->right = NULL;
   newnode->val = val;
   if (!parent) {
      t->root = newnode;
      return;
   }
   if (val < parent->val)
      parent->left = newnode;
   else
      parent->right = newnode;
   return;
}

