/*
 * Copyright (c) 2019 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SRC_VPPINFRA_RBTREE_H_
#define SRC_VPPINFRA_RBTREE_H_

#include <vppinfra/types.h>
#include <vppinfra/pool.h>

#define RBTREE_TNIL_INDEX 0

typedef u32 rb_node_index_t;

typedef enum rb_tree_color_
{
  RBTREE_RED,
  RBTREE_BLACK
} rb_node_color_t;

typedef struct rb_node_
{
  u8 color;			/**< node color */
  rb_node_index_t parent;	/**< parent index */
  rb_node_index_t left;		/**< left child index */
  rb_node_index_t right;	/**< right child index */
  u32 key;			/**< node key */
  uword opaque;			/**< value stored by node */
} rb_node_t;

typedef struct rb_tree_
{
  rb_node_t *nodes;		/**< pool of nodes */
  rb_node_index_t root;		/**< root index */
} rb_tree_t;

typedef int (*rb_tree_lt_fn) (u32 a, u32 b);

void rb_tree_init (rb_tree_t * rt);
rb_node_index_t rb_tree_add (rb_tree_t * rt, u32 key);
rb_node_index_t rb_tree_add2 (rb_tree_t * rt, u32 key, uword opaque);
rb_node_index_t rb_tree_add_custom (rb_tree_t * rt, u32 key, uword opaque,
				    rb_tree_lt_fn ltfn);
void rb_tree_del (rb_tree_t * rt, u32 key);
void rb_tree_del_node (rb_tree_t * rt, rb_node_t * z);
void rb_tree_del_custom (rb_tree_t * rt, u32 key, rb_tree_lt_fn ltfn);
void rb_tree_free_nodes (rb_tree_t * rt);
u32 rb_tree_n_nodes (rb_tree_t * rt);
rb_node_t *rb_tree_min_subtree (rb_tree_t * rt, rb_node_t * x);
rb_node_t *rb_tree_max_subtree (rb_tree_t * rt, rb_node_t * x);
rb_node_t *rb_tree_search_subtree (rb_tree_t * rt, rb_node_t * x, u32 key);
rb_node_t *rb_tree_search_subtree_custom (rb_tree_t * rt, rb_node_t * x,
					  u32 key, rb_tree_lt_fn ltfn);
rb_node_t *rb_tree_successor (rb_tree_t * rt, rb_node_t * x);
rb_node_t *rb_tree_predecessor (rb_tree_t * rt, rb_node_t * x);
int rb_tree_is_init (rb_tree_t * rt);

static inline rb_node_index_t
rb_node_index (rb_tree_t * rt, rb_node_t * n)
{
  return n - rt->nodes;
}

static inline u8
rb_node_is_tnil (rb_tree_t * rt, rb_node_t * n)
{
  return rb_node_index (rt, n) == RBTREE_TNIL_INDEX;
}

static inline rb_node_t *
rb_node (rb_tree_t * rt, rb_node_index_t ri)
{
  return pool_elt_at_index (rt->nodes, ri);
}

static inline rb_node_t *
rb_node_right (rb_tree_t * rt, rb_node_t * n)
{
  return pool_elt_at_index (rt->nodes, n->right);
}

static inline rb_node_t *
rb_node_left (rb_tree_t * rt, rb_node_t * n)
{
  return pool_elt_at_index (rt->nodes, n->left);
}

static inline rb_node_t *
rb_node_parent (rb_tree_t * rt, rb_node_t * n)
{
  return pool_elt_at_index (rt->nodes, n->parent);
}

#endif /* SRC_VPPINFRA_RBTREE_H_ */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
