mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
254 lines
8.5 KiB
C
254 lines
8.5 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
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; version 2 of the License.
|
|
|
|
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, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
/******************************************************************//**
|
|
@file include/ut0rbt.h
|
|
Various utilities
|
|
|
|
Created 2007-03-20 Sunny Bains
|
|
*******************************************************/
|
|
|
|
#ifndef INNOBASE_UT0RBT_H
|
|
#define INNOBASE_UT0RBT_H
|
|
|
|
#if !defined(IB_RBT_TESTING)
|
|
#include "ut0mem.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#define ut_malloc malloc
|
|
#define ut_free free
|
|
#define ulint unsigned long
|
|
#define ut_a(c) assert(c)
|
|
#define ut_error assert(0)
|
|
#define ibool unsigned int
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#endif
|
|
|
|
struct ib_rbt_node_t;
|
|
typedef void (*ib_rbt_print_node)(const ib_rbt_node_t* node);
|
|
typedef int (*ib_rbt_compare)(const void* p1, const void* p2);
|
|
typedef int (*ib_rbt_arg_compare)(const void*, const void* p1, const void* p2);
|
|
|
|
/** Red black tree color types */
|
|
enum ib_rbt_color_t {
|
|
IB_RBT_RED,
|
|
IB_RBT_BLACK
|
|
};
|
|
|
|
/** Red black tree node */
|
|
struct ib_rbt_node_t {
|
|
ib_rbt_color_t color; /* color of this node */
|
|
|
|
ib_rbt_node_t* left; /* points left child */
|
|
ib_rbt_node_t* right; /* points right child */
|
|
ib_rbt_node_t* parent; /* points parent node */
|
|
|
|
char value[1]; /* Data value */
|
|
};
|
|
|
|
/** Red black tree instance.*/
|
|
struct ib_rbt_t {
|
|
ib_rbt_node_t* nil; /* Black colored node that is
|
|
used as a sentinel. This is
|
|
pre-allocated too.*/
|
|
|
|
ib_rbt_node_t* root; /* Root of the tree, this is
|
|
pre-allocated and the first
|
|
data node is the left child.*/
|
|
|
|
ulint n_nodes; /* Total number of data nodes */
|
|
|
|
ib_rbt_compare compare; /* Fn. to use for comparison */
|
|
ib_rbt_arg_compare
|
|
compare_with_arg; /* Fn. to use for comparison
|
|
with argument */
|
|
ulint sizeof_value; /* Sizeof the item in bytes */
|
|
void* cmp_arg; /* Compare func argument */
|
|
};
|
|
|
|
/** The result of searching for a key in the tree, this is useful for
|
|
a speedy lookup and insert if key doesn't exist.*/
|
|
struct ib_rbt_bound_t {
|
|
const ib_rbt_node_t*
|
|
last; /* Last node visited */
|
|
|
|
int result; /* Result of comparing with
|
|
the last non-nil node that
|
|
was visited */
|
|
};
|
|
|
|
/* Size in elements (t is an rb tree instance) */
|
|
#define rbt_size(t) (t->n_nodes)
|
|
|
|
/* Check whether the rb tree is empty (t is an rb tree instance) */
|
|
#define rbt_empty(t) (rbt_size(t) == 0)
|
|
|
|
/* Get data value (t is the data type, n is an rb tree node instance) */
|
|
#define rbt_value(t, n) ((t*) &n->value[0])
|
|
|
|
/* Compare a key with the node value (t is tree, k is key, n is node)*/
|
|
#define rbt_compare(t, k, n) (t->compare(k, n->value))
|
|
|
|
/**********************************************************************//**
|
|
Free an instance of a red black tree */
|
|
void
|
|
rbt_free(
|
|
/*=====*/
|
|
ib_rbt_t* tree); /*!< in: rb tree to free */
|
|
/**********************************************************************//**
|
|
Create an instance of a red black tree
|
|
@return rb tree instance */
|
|
ib_rbt_t*
|
|
rbt_create(
|
|
/*=======*/
|
|
size_t sizeof_value, /*!< in: size in bytes */
|
|
ib_rbt_compare compare); /*!< in: comparator */
|
|
/**********************************************************************//**
|
|
Create an instance of a red black tree, whose comparison function takes
|
|
an argument
|
|
@return rb tree instance */
|
|
ib_rbt_t*
|
|
rbt_create_arg_cmp(
|
|
/*===============*/
|
|
size_t sizeof_value, /*!< in: size in bytes */
|
|
ib_rbt_arg_compare
|
|
compare, /*!< in: comparator */
|
|
void* cmp_arg); /*!< in: compare fn arg */
|
|
/**********************************************************************//**
|
|
Delete a node from the red black tree, identified by key */
|
|
ibool
|
|
rbt_delete(
|
|
/*=======*/
|
|
/* in: TRUE on success */
|
|
ib_rbt_t* tree, /* in: rb tree */
|
|
const void* key); /* in: key to delete */
|
|
/**********************************************************************//**
|
|
Remove a node from the red black tree, NOTE: This function will not delete
|
|
the node instance, THAT IS THE CALLERS RESPONSIBILITY.
|
|
@return the deleted node with the const. */
|
|
ib_rbt_node_t*
|
|
rbt_remove_node(
|
|
/*============*/
|
|
ib_rbt_t* tree, /*!< in: rb tree */
|
|
const ib_rbt_node_t*
|
|
node); /*!< in: node to delete, this
|
|
is a fudge and declared const
|
|
because the caller has access
|
|
only to const nodes.*/
|
|
/**********************************************************************//**
|
|
Add data to the red black tree, identified by key (no dups yet!)
|
|
@return inserted node */
|
|
const ib_rbt_node_t*
|
|
rbt_insert(
|
|
/*=======*/
|
|
ib_rbt_t* tree, /*!< in: rb tree */
|
|
const void* key, /*!< in: key for ordering */
|
|
const void* value); /*!< in: data that will be
|
|
copied to the node.*/
|
|
/**********************************************************************//**
|
|
Add a new node to the tree, useful for data that is pre-sorted.
|
|
@return appended node */
|
|
const ib_rbt_node_t*
|
|
rbt_add_node(
|
|
/*=========*/
|
|
ib_rbt_t* tree, /*!< in: rb tree */
|
|
ib_rbt_bound_t* parent, /*!< in: parent */
|
|
const void* value); /*!< in: this value is copied
|
|
to the node */
|
|
/**********************************************************************//**
|
|
Return the left most data node in the tree
|
|
@return left most node */
|
|
const ib_rbt_node_t*
|
|
rbt_first(
|
|
/*======*/
|
|
const ib_rbt_t* tree); /*!< in: rb tree */
|
|
/**********************************************************************//**
|
|
Return the right most data node in the tree
|
|
@return right most node */
|
|
const ib_rbt_node_t*
|
|
rbt_last(
|
|
/*=====*/
|
|
const ib_rbt_t* tree); /*!< in: rb tree */
|
|
/**********************************************************************//**
|
|
Return the next node from current.
|
|
@return successor node to current that is passed in. */
|
|
const ib_rbt_node_t*
|
|
rbt_next(
|
|
/*=====*/
|
|
const ib_rbt_t* tree, /*!< in: rb tree */
|
|
const ib_rbt_node_t* /* in: current node */
|
|
current);
|
|
/**********************************************************************//**
|
|
Return the prev node from current.
|
|
@return precedessor node to current that is passed in */
|
|
const ib_rbt_node_t*
|
|
rbt_prev(
|
|
/*=====*/
|
|
const ib_rbt_t* tree, /*!< in: rb tree */
|
|
const ib_rbt_node_t* /* in: current node */
|
|
current);
|
|
/**********************************************************************//**
|
|
Search for the key, a node will be retuned in parent.last, whether it
|
|
was found or not. If not found then parent.last will contain the
|
|
parent node for the possibly new key otherwise the matching node.
|
|
@return result of last comparison */
|
|
int
|
|
rbt_search(
|
|
/*=======*/
|
|
const ib_rbt_t* tree, /*!< in: rb tree */
|
|
ib_rbt_bound_t* parent, /*!< in: search bounds */
|
|
const void* key); /*!< in: key to search */
|
|
/**********************************************************************//**
|
|
Search for the key, a node will be retuned in parent.last, whether it
|
|
was found or not. If not found then parent.last will contain the
|
|
parent node for the possibly new key otherwise the matching node.
|
|
@return result of last comparison */
|
|
int
|
|
rbt_search_cmp(
|
|
/*===========*/
|
|
const ib_rbt_t* tree, /*!< in: rb tree */
|
|
ib_rbt_bound_t* parent, /*!< in: search bounds */
|
|
const void* key, /*!< in: key to search */
|
|
ib_rbt_compare compare, /*!< in: comparator */
|
|
ib_rbt_arg_compare
|
|
arg_compare); /*!< in: fn to compare items
|
|
with argument */
|
|
/**********************************************************************//**
|
|
Merge the node from dst into src. Return the number of nodes merged.
|
|
@return no. of recs merged */
|
|
ulint
|
|
rbt_merge_uniq(
|
|
/*===========*/
|
|
ib_rbt_t* dst, /*!< in: dst rb tree */
|
|
const ib_rbt_t* src); /*!< in: src rb tree */
|
|
#if defined UNIV_DEBUG || defined IB_RBT_TESTING
|
|
/**********************************************************************//**
|
|
Verify the integrity of the RB tree. For debugging. 0 failure else height
|
|
of tree (in count of black nodes).
|
|
@return TRUE if OK FALSE if tree invalid. */
|
|
ibool
|
|
rbt_validate(
|
|
/*=========*/
|
|
const ib_rbt_t* tree); /*!< in: tree to validate */
|
|
#endif /* UNIV_DEBUG || IB_RBT_TESTING */
|
|
|
|
#endif /* INNOBASE_UT0RBT_H */
|