/*********************************************************************** Copyright (c) 2012, 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, Suite 500, Boston, MA 02110-1335 USA ***********************************************************************/ /**************************************************//** @file innodb_list.h Created 03/15/2011 Jimmy Yang (most macros and defines are adopted from utility files in the InnoDB. Namely ut/ut0lst.h, ut0rnd.h and hash0hash.h etc.) *******************************************************/ #ifndef INNODB_UTILITY_H #define INNODB_UTILITY_H #include "config.h" #include "api0api.h" #define UT_LIST_NODE_T(TYPE) \ struct { \ TYPE* prev; /*!< pointer to the previous node, \ NULL if start of list */ \ TYPE* next; /*!< pointer to next node, NULL if end of list */\ } \ #define UT_LIST_BASE_NODE_T(TYPE) \ struct { \ int count; /*!< count of nodes in list */ \ TYPE * start; /*!< pointer to list start, NULL if empty */ \ TYPE * end; /*!< pointer to list end, NULL if empty */ \ } /** Some Macros to manipulate the list, extracted from "ut0lst.h" */ #define UT_LIST_INIT(BASE) \ { \ (BASE).count = 0; \ (BASE).start = NULL; \ (BASE).end = NULL; \ } \ #define UT_LIST_ADD_LAST(NAME, BASE, N) \ { \ ((BASE).count)++; \ ((N)->NAME).prev = (BASE).end; \ ((N)->NAME).next = NULL; \ if ((BASE).end != NULL) { \ (((BASE).end)->NAME).next = (N); \ } \ (BASE).end = (N); \ if ((BASE).start == NULL) { \ (BASE).start = (N); \ } \ } \ #define UT_LIST_ADD_FIRST(NAME, BASE, N) \ { \ ((BASE).count)++; \ ((N)->NAME).next = (BASE).start; \ ((N)->NAME).prev = NULL; \ if (UNIV_LIKELY((BASE).start != NULL)) { \ (((BASE).start)->NAME).prev = (N); \ } \ (BASE).start = (N); \ if (UNIV_UNLIKELY((BASE).end == NULL)) { \ (BASE).end = (N); \ } \ } \ # define UT_LIST_REMOVE_CLEAR(NAME, N) \ ((N)->NAME.prev = (N)->NAME.next = (void*) -1) /** Removes a node from a linked list. */ #define UT_LIST_REMOVE(NAME, BASE, N) \ do { \ ((BASE).count)--; \ if (((N)->NAME).next != NULL) { \ ((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev; \ } else { \ (BASE).end = ((N)->NAME).prev; \ } \ if (((N)->NAME).prev != NULL) { \ ((((N)->NAME).prev)->NAME).next = ((N)->NAME).next; \ } else { \ (BASE).start = ((N)->NAME).next; \ } \ UT_LIST_REMOVE_CLEAR(NAME, N); \ } while (0) #define UT_LIST_GET_NEXT(NAME, N) (((N)->NAME).next) #define UT_LIST_GET_LEN(BASE) (BASE).count #define UT_LIST_GET_FIRST(BASE) (BASE).start /*************************************************************//** Folds a character string ending in the null character. Extracted from ut0rnd.h and ut0rnd.ic. @return folded value */ ib_ulint_t ut_fold_string( /*===========*/ const char* str); /*!< in: null-terminated string */ typedef struct hash_cell_struct{ void* node; /*!< hash chain node, NULL if none */ } hash_cell_t; typedef struct hash_table_struct { ib_ulint_t n_cells;/* number of cells in the hash table */ hash_cell_t* array; /*!< pointer to cell array */ } hash_table_t; #define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA) \ do { \ hash_cell_t* cell3333; \ TYPE* struct3333; \ \ \ (DATA)->NAME = NULL; \ \ cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\ \ if (cell3333->node == NULL) { \ cell3333->node = DATA; \ } else { \ struct3333 = (TYPE*) cell3333->node; \ \ while (struct3333->NAME != NULL) { \ \ struct3333 = (TYPE*) struct3333->NAME;\ } \ \ struct3333->NAME = DATA; \ } \ } while (0) /*******************************************************************//** Gets the first struct in a hash chain, NULL if none. */ #define HASH_GET_FIRST(TABLE, HASH_VAL) \ (hash_get_nth_cell(TABLE, HASH_VAL)->node) /*******************************************************************//** Gets the next struct in a hash chain, NULL if none. */ #define HASH_GET_NEXT(NAME, DATA) ((DATA)->NAME) /********************************************************************//** Looks for a struct in a hash table. */ #define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, TEST) \ { \ (DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\ \ while ((DATA) != NULL) { \ if (TEST) { \ break; \ } else { \ (DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA); \ } \ } \ } /********************************************************************//** Cleanup items in a hash table */ #define HASH_CLEANUP(TABLE, TYPE) \ do { \ ib_ulint_t i; \ TYPE data; \ \ for (i = 0; i < TABLE->n_cells; i++) { \ data = (TYPE) HASH_GET_FIRST(TABLE, i); \ \ while (data) { \ TYPE next_data; \ next_data = HASH_GET_NEXT(name_hash, data); \ innodb_config_free(data); \ free(data); \ data = next_data; \ } \ } \ \ free(TABLE->array); \ free(TABLE); \ } while(0) /************************************************************//** Gets the nth cell in a hash table. @return pointer to cell */ hash_cell_t* hash_get_nth_cell( /*==============*/ hash_table_t* table, /*!< in: hash table */ ib_ulint_t n); /*!< in: cell index */ /*************************************************************//** Creates a hash table with >= n array cells. The actual number of cells is chosen to be a prime number slightly bigger than n. @return own: created table */ hash_table_t* hash_create( /*========*/ ib_ulint_t n); /*!< in: number of array cells */ /**************************************************************//** Calculates the hash value from a folded value. @return hashed value */ ib_ulint_t hash_calc_hash( /*===========*/ ib_ulint_t fold, /*!< in: folded value */ hash_table_t* table); /*!< in: hash table */ #endif /* INNODB_UTILITY_H */