LCOV - code coverage report
Current view: top level - tommyds/tommyds - tommytypes.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 16 16 100.0 %
Date: 2018-04-02 17:50:51 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved.
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions
       6             :  * are met:
       7             :  *
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  *
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  *
      15             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      16             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      17             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      18             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      19             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      20             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      21             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      22             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      23             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      24             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      25             :  * POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : /** \file
      28             :  * Generic types.
      29             :  */
      30             : 
      31             : #ifndef __TOMMYTYPES_H
      32             : #define __TOMMYTYPES_H
      33             : 
      34             : /******************************************************************************/
      35             : /* types */
      36             : 
      37             : #include <stddef.h>
      38             : 
      39             : #ifdef _MSC_VER
      40             : typedef unsigned tommy_uint32_t; /**< Generic uint32_t type. */
      41             : typedef unsigned _int64 tommy_uint64_t; /**< Generic uint64_t type. */
      42             : typedef size_t tommy_uintptr_t; /**< Generic uintptr_t type. */
      43             : #ifdef _WIN64
      44             : #define TOMMY_SIZE_BIT 64
      45             : typedef unsigned _int64_t tommy_size_t; /**< Generic size_t type. */
      46             : typedef _int64_t tommy_ssize_t; /**< Generic ssize_t type. */
      47             : #else
      48             : #define TOMMY_SIZE_BIT 32
      49             : typedef unsigned tommy_size_t; /**< Generic size_t type. */
      50             : typedef int tommy_ssize_t; /**< Generic ssize_t type. */
      51             : #endif
      52             : #else
      53             : #include <stdint.h>
      54             : typedef uint32_t tommy_uint32_t; /**< Generic uint32_t type. */
      55             : typedef uint64_t tommy_uint64_t; /**< Generic uint64_t type. */
      56             : typedef uintptr_t tommy_uintptr_t; /**< Generic uintptr_t type. */
      57             : #if SIZE_MAX == UINT64_MAX
      58             : #define TOMMY_SIZE_BIT 64
      59             : typedef uint64_t tommy_size_t; /**< Generic size_t type. */
      60             : typedef int64_t tommy_ssize_t; /**< Generic ssize_t type. */
      61             : #elif SIZE_MAX == UINT32_MAX
      62             : #define TOMMY_SIZE_BIT 32
      63             : typedef uint32_t tommy_size_t; /**< Generic size_t type. */
      64             : typedef int32_t tommy_ssize_t; /**< Generic ssize_t type. */
      65             : #else
      66             : #error Unsupported SIZE_MAX
      67             : #endif
      68             : #endif
      69             : 
      70             : typedef ptrdiff_t tommy_ptrdiff_t; /**< Generic ptrdiff_t type. */
      71             : typedef int tommy_bool_t; /**< Generic boolean type. */
      72             : 
      73             : /**
      74             :  * Generic unsigned integer type.
      75             :  *
      76             :  * It has no specific size, as is used to store only small values.
      77             :  * To make the code more efficient, a full 32 bit integer is used.
      78             :  */
      79             : typedef tommy_uint32_t tommy_uint_t;
      80             : 
      81             : /** \internal
      82             :  * Type cast required for the C++ compilation.
      83             :  * When compiling in C++ we cannot convert a void* pointer to another pointer.
      84             :  * In such case we need an explicit cast.
      85             :  */
      86             : #ifdef __cplusplus
      87             : #define tommy_cast(type, value) static_cast<type>(value)
      88             : #else
      89             : #define tommy_cast(type, value) (value)
      90             : #endif
      91             : 
      92             : /******************************************************************************/
      93             : /* heap */
      94             : 
      95             : /* by default uses malloc/calloc/realloc/free */
      96             : 
      97             : /**
      98             :  * Generic malloc(), calloc(), realloc() and free() functions.
      99             :  * Redefine them to what you need. By default they map to the C malloc(), calloc(), realloc() and free().
     100             :  */
     101             : #if !defined(tommy_malloc) || !defined(tommy_calloc) || !defined(tommy_realloc) || !defined(tommy_free)
     102             : #include <stdlib.h>
     103             : #endif
     104             : #if !defined(tommy_malloc)
     105             : #define tommy_malloc malloc
     106             : #endif
     107             : #if !defined(tommy_calloc)
     108             : #define tommy_calloc calloc
     109             : #endif
     110             : #if !defined(tommy_realloc)
     111             : #define tommy_realloc realloc
     112             : #endif
     113             : #if !defined(tommy_free)
     114             : #define tommy_free free
     115             : #endif
     116             : 
     117             : /******************************************************************************/
     118             : /* modificators */
     119             : 
     120             : /** \internal
     121             :  * Definition of the inline keyword if available.
     122             :  */
     123             : #if !defined(tommy_inline)
     124             : #if defined(_MSC_VER) || defined(__GNUC__)
     125             : #define tommy_inline static __inline
     126             : #else
     127             : #define tommy_inline static
     128             : #endif
     129             : #endif
     130             : 
     131             : /** \internal
     132             :  * Definition of the restrict keyword if available.
     133             :  */
     134             : #if !defined(tommy_restrict)
     135             : #if __STDC_VERSION__ >= 199901L
     136             : #define tommy_restrict restrict
     137             : #elif defined(_MSC_VER) || defined(__GNUC__)
     138             : #define tommy_restrict __restrict
     139             : #else
     140             : #define tommy_restrict
     141             : #endif
     142             : #endif
     143             : 
     144             : /** \internal
     145             :  * Hints the compiler that a condition is likely true.
     146             :  */
     147             : #if !defined(tommy_likely)
     148             : #if defined(__GNUC__)
     149             : #define tommy_likely(x) __builtin_expect(!!(x), 1)
     150             : #else
     151             : #define tommy_likely(x) (x)
     152             : #endif
     153             : #endif
     154             : 
     155             : /** \internal
     156             :  * Hints the compiler that a condition is likely false.
     157             :  */
     158             : #if !defined(tommy_unlikely)
     159             : #if defined(__GNUC__)
     160             : #define tommy_unlikely(x) __builtin_expect(!!(x), 0)
     161             : #else
     162             : #define tommy_unlikely(x) (x)
     163             : #endif
     164             : #endif
     165             : 
     166             : /******************************************************************************/
     167             : /* key/hash */
     168             : 
     169             : /**
     170             :  * Type used in indexed data structures to store the key of a object.
     171             :  */
     172             : typedef tommy_size_t tommy_key_t;
     173             : 
     174             : /**
     175             :  * Type used in hashtables to store the hash of a object.
     176             :  */
     177             : typedef tommy_size_t tommy_hash_t;
     178             : 
     179             : /******************************************************************************/
     180             : /* node */
     181             : 
     182             : /**
     183             :  * Data structure node.
     184             :  * This node type is shared between all the data structures and used to store some
     185             :  * info directly into the objects you want to store.
     186             :  *
     187             :  * A typical declaration is:
     188             :  * \code
     189             :  * struct object {
     190             :  *     tommy_node node;
     191             :  *     // other fields
     192             :  * };
     193             :  * \endcode
     194             :  */
     195             : typedef struct tommy_node_struct {
     196             :         /**
     197             :          * Next node.
     198             :          * The tail node has it at 0, like a 0 terminated list.
     199             :          */
     200             :         struct tommy_node_struct* next;
     201             : 
     202             :         /**
     203             :          * Previous node.
     204             :          * The head node points to the tail node, like a circular list.
     205             :          */
     206             :         struct tommy_node_struct* prev;
     207             : 
     208             :         /**
     209             :          * Pointer to the object containing the node.
     210             :          * This field is initialized when inserting nodes into a data structure.
     211             :          */
     212             :         void* data;
     213             : 
     214             :         /**
     215             :          * Index of the node.
     216             :          * With tries this field is used to store the key.
     217             :          * With hashtables this field is used to store the hash value.
     218             :          * With lists this field is not used.
     219             :          */
     220             :         tommy_size_t index;
     221             : } tommy_node;
     222             : 
     223             : /******************************************************************************/
     224             : /* compare */
     225             : 
     226             : /**
     227             :  * Compare function for elements.
     228             :  * \param obj_a Pointer to the first object to compare.
     229             :  * \param obj_b Pointer to the second object to compare.
     230             :  * \return <0 if the first element is less than the second, ==0 equal, >0 if greather.
     231             :  *
     232             :  * This function is like the C strcmp().
     233             :  *
     234             :  * \code
     235             :  * struct object {
     236             :  *     tommy_node node;
     237             :  *     int value;
     238             :  * };
     239             :  *
     240             :  * int compare(const void* obj_a, const void* obj_b)
     241             :  * {
     242             :  *     if (((const struct object*)obj_a)->value < ((const struct object*)obj_b)->value)
     243             :  *         return -1;
     244             :  *     if (((const struct object*)obj_a)->value > ((const struct object*)obj_b)->value)
     245             :  *         return 1;
     246             :  *     return 0;
     247             :  * }
     248             :  *
     249             :  * tommy_list_sort(&list, compare);
     250             :  * \endcode
     251             :  *
     252             :  */
     253             : typedef int tommy_compare_func(const void* obj_a, const void* obj_b);
     254             : 
     255             : /**
     256             :  * Search function for elements.
     257             :  * \param arg Pointer to the value to search as passed at the search function.
     258             :  * \param obj Pointer to the object to compare to.
     259             :  * \return ==0 if the value matches the element. !=0 if different.
     260             :  *
     261             :  * The first argument is a pointer to the value to search exactly
     262             :  * as it's passed at the search function called.
     263             :  * The second argument is a pointer to the object inside the hashtable to compare.
     264             :  *
     265             :  * The return value has to be 0 if the values are equal. != 0 if they are different.
     266             :  *
     267             :  * \code
     268             :  * struct object {
     269             :  *     tommy_node node;
     270             :  *     int value;
     271             :  * };
     272             :  *
     273             :  * int compare(const void* arg, const void* obj)
     274             :  * {
     275             :  *     const int* value_to_find = arg;
     276             :  *     const struct object* object_to_compare = obj;
     277             :  *
     278             :  *     return *value_to_find != object_to_compare->value;
     279             :  * }
     280             :  *
     281             :  * int value_to_find = 1;
     282             :  * struct object* obj = tommy_hashtable_search(&hashtable, compare, &value_to_find, tommy_inthash_u32(value_to_find));
     283             :  * if (!obj) {
     284             :  *     // not found
     285             :  * } else {
     286             :  *     // found
     287             :  * }
     288             :  * \endcode
     289             :  *
     290             :  */
     291             : typedef int tommy_search_func(const void* arg, const void* obj);
     292             : 
     293             : /**
     294             :  * Foreach function.
     295             :  * \param obj Pointer to the object to iterate.
     296             :  *
     297             :  * A typical example is to use free() to deallocate all the objects in a list.
     298             :  * \code
     299             :  * tommy_list_foreach(&list, (tommy_foreach_func*)free);
     300             :  * \endcode
     301             :  */
     302             : typedef void tommy_foreach_func(void* obj);
     303             : 
     304             : /**
     305             :  * Foreach function with an argument.
     306             :  * \param arg Pointer to a generic argument.
     307             :  * \param obj Pointer to the object to iterate.
     308             :  */
     309             : typedef void tommy_foreach_arg_func(void* arg, void* obj);
     310             : 
     311             : /******************************************************************************/
     312             : /* bit hacks */
     313             : 
     314             : #if defined(_MSC_VER) && !defined(__cplusplus)
     315             : #include <intrin.h>
     316             : #pragma intrinsic(_BitScanReverse)
     317             : #pragma intrinsic(_BitScanForward)
     318             : #if TOMMY_SIZE_BIT == 64
     319             : #pragma intrinsic(_BitScanReverse64)
     320             : #pragma intrinsic(_BitScanForward64)
     321             : #endif
     322             : #endif
     323             : 
     324             : /** \internal
     325             :  * Integer log2 for constants.
     326             :  * You can use it only for exact power of 2 up to 256.
     327             :  */
     328             : #define TOMMY_ILOG2(value) ((value) == 256 ? 8 : (value) == 128 ? 7 : (value) == 64 ? 6 : (value) == 32 ? 5 : (value) == 16 ? 4 : (value) == 8 ? 3 : (value) == 4 ? 2 : (value) == 2 ? 1 : 0)
     329             : 
     330             : /**
     331             :  * Bit scan reverse or integer log2.
     332             :  * Return the bit index of the most significant 1 bit.
     333             :  *
     334             :  * If no bit is set, the result is undefined.
     335             :  * To force a return 0 in this case, you can use tommy_ilog2_u32(value | 1).
     336             :  *
     337             :  * Other interesting ways for bitscan are at:
     338             :  *
     339             :  * Bit Twiddling Hacks
     340             :  * http://graphics.stanford.edu/~seander/bithacks.html
     341             :  *
     342             :  * Chess Programming BitScan
     343             :  * http://chessprogramming.wikispaces.com/BitScan
     344             :  *
     345             :  * \param value Value to scan. 0 is not allowed.
     346             :  * \return The index of the most significant bit set.
     347             :  */
     348             : tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
     349             : {
     350             : #if defined(_MSC_VER)
     351             :         unsigned long count;
     352             :         _BitScanReverse(&count, value);
     353             :         return count;
     354             : #elif defined(__GNUC__)
     355             :         /*
     356             :          * GCC implements __builtin_clz(x) as "__builtin_clz(x) = bsr(x) ^ 31"
     357             :          *
     358             :          * Where "x ^ 31 = 31 - x", but gcc does not optimize "31 - __builtin_clz(x)" to bsr(x),
     359             :          * but generates 31 - (bsr(x) xor 31).
     360             :          *
     361             :          * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)",
     362             :          * to allow the double xor to be optimized out.
     363             :          */
     364             :         return __builtin_clz(value) ^ 31;
     365             : #else
     366             :         /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */
     367             :         /* from http://graphics.stanford.edu/~seander/bithacks.html */
     368             :         static unsigned char TOMMY_DE_BRUIJN_INDEX_ILOG2[32] = {
     369             :                 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
     370             :                 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
     371             :         };
     372             : 
     373             :         value |= value >> 1;
     374             :         value |= value >> 2;
     375             :         value |= value >> 4;
     376             :         value |= value >> 8;
     377             :         value |= value >> 16;
     378             : 
     379             :         return TOMMY_DE_BRUIJN_INDEX_ILOG2[(tommy_uint32_t)(value * 0x07C4ACDDU) >> 27];
     380             : #endif
     381             : }
     382             : 
     383             : #if TOMMY_SIZE_BIT == 64
     384             : /**
     385             :  * Bit scan reverse or integer log2 for 64 bits.
     386             :  */
     387   908497031 : tommy_inline tommy_uint_t tommy_ilog2_u64(tommy_uint64_t value)
     388             : {
     389             : #if defined(_MSC_VER)
     390             :         unsigned long count;
     391             :         _BitScanReverse64(&count, value);
     392             :         return count;
     393             : #elif defined(__GNUC__)
     394   908497031 :         return __builtin_clzll(value) ^ 63;
     395             : #else
     396             :         uint32_t l = value & 0xFFFFFFFFU;
     397             :         uint32_t h = value >> 32;
     398             :         if (h)
     399             :                 return tommy_ilog2_u32(h) + 32;
     400             :         else
     401             :                 return tommy_ilog2_u32(l);
     402             : #endif
     403             : }
     404             : #endif
     405             : 
     406             : /**
     407             :  * Bit scan forward or trailing zero count.
     408             :  * Return the bit index of the least significant 1 bit.
     409             :  *
     410             :  * If no bit is set, the result is undefined.
     411             :  * \param value Value to scan. 0 is not allowed.
     412             :  * \return The index of the least significant bit set.
     413             :  */
     414             : tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value)
     415             : {
     416             : #if defined(_MSC_VER)
     417             :         unsigned long count;
     418             :         _BitScanForward(&count, value);
     419             :         return count;
     420             : #elif defined(__GNUC__)
     421             :         return __builtin_ctz(value);
     422             : #else
     423             :         /* Count the consecutive zero bits (trailing) on the right with multiply and lookup */
     424             :         /* from http://graphics.stanford.edu/~seander/bithacks.html */
     425             :         static const unsigned char TOMMY_DE_BRUIJN_INDEX_CTZ[32] = {
     426             :                 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
     427             :                 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
     428             :         };
     429             : 
     430             :         return TOMMY_DE_BRUIJN_INDEX_CTZ[(tommy_uint32_t)(((value & - value) * 0x077CB531U)) >> 27];
     431             : #endif
     432             : }
     433             : 
     434             : #if TOMMY_SIZE_BIT == 64
     435             : /**
     436             :  * Bit scan forward or trailing zero count for 64 bits.
     437             :  */
     438           5 : tommy_inline tommy_uint_t tommy_ctz_u64(tommy_uint64_t value)
     439             : {
     440             : #if defined(_MSC_VER)
     441             :         unsigned long count;
     442             :         _BitScanForward64(&count, value);
     443             :         return count;
     444             : #elif defined(__GNUC__)
     445           5 :         return __builtin_ctzll(value);
     446             : #else
     447             :         uint32_t l = value & 0xFFFFFFFFU;
     448             :         uint32_t h = value >> 32;
     449             :         if (l)
     450             :                 return tommy_ctz_u32(l);
     451             :         else
     452             :                 return tommy_ctz_u32(h) + 32;
     453             : #endif
     454             : }
     455             : #endif
     456             : 
     457             : /**
     458             :  * Rounds up to the next power of 2.
     459             :  * For the value 0, the result is undefined.
     460             :  * \return The smallest power of 2 not less than the specified value.
     461             :  */
     462             : tommy_inline tommy_uint32_t tommy_roundup_pow2_u32(tommy_uint32_t value)
     463             : {
     464             :         /* Round up to the next highest power of 2 */
     465             :         /* from http://graphics.stanford.edu/~seander/bithacks.html */
     466             : 
     467             :         --value;
     468             :         value |= value >> 1;
     469             :         value |= value >> 2;
     470             :         value |= value >> 4;
     471             :         value |= value >> 8;
     472             :         value |= value >> 16;
     473             :         ++value;
     474             : 
     475             :         return value;
     476             : }
     477             : 
     478             : /**
     479             :  * Rounds up to the next power of 2 for 64 bits.
     480             :  */
     481        5064 : tommy_inline tommy_uint64_t tommy_roundup_pow2_u64(tommy_uint64_t value)
     482             : {
     483        5064 :         --value;
     484        5064 :         value |= value >> 1;
     485        5064 :         value |= value >> 2;
     486        5064 :         value |= value >> 4;
     487        5064 :         value |= value >> 8;
     488        5064 :         value |= value >> 16;
     489        5064 :         value |= value >> 32;
     490        5064 :         ++value;
     491             : 
     492        5064 :         return value;
     493             : }
     494             : 
     495             : /**
     496             :  * Check if the specified word has a byte at 0.
     497             :  * \return 0 or 1.
     498             :  */
     499    67108949 : tommy_inline int tommy_haszero_u32(tommy_uint32_t value)
     500             : {
     501    67108949 :         return ((value - 0x01010101) & ~value & 0x80808080) != 0;
     502             : }
     503             : 
     504             : /*
     505             :  * Bit depth mapping.
     506             :  */
     507             : #if TOMMY_SIZE_BIT == 64
     508             : #define tommy_ilog2 tommy_ilog2_u64
     509             : #define tommy_ctz tommy_ctz_u64
     510             : #define tommy_roundup_pow2 tommy_roundup_pow2_u64
     511             : #else
     512             : #define tommy_ilog2 tommy_ilog2_u32
     513             : #define tommy_ctz tommy_ctz_u32
     514             : #define tommy_roundup_pow2 tommy_roundup_pow2_u32
     515             : #endif
     516             : 
     517             : #endif
     518             : 

Generated by: LCOV version 1.13