You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
8.1 KiB
172 lines
8.1 KiB
#ifndef _DEPOOLHASHARRAY_H
|
|
#define _DEPOOLHASHARRAY_H
|
|
/*-------------------------------------------------------------------------
|
|
* drawElements Memory Pool Library
|
|
* --------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* 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.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Memory pool hash-array class.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deDefs.h"
|
|
#include "dePoolHash.h"
|
|
#include "dePoolArray.h"
|
|
|
|
DE_BEGIN_EXTERN_C
|
|
|
|
void dePoolHashArray_selfTest (void);
|
|
|
|
DE_END_EXTERN_C
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Declare a template pool hash-array (array with hash) class interface.
|
|
* \param TYPENAME Type name of the declared hash-array.
|
|
* \param KEYTYPE Type of the key.
|
|
* \param VALUETYPE Type of the value.
|
|
* \param KEYARRAYTYPE Type of the key array.
|
|
* \param VALUEARRAYTYPE Type of the value array.
|
|
*
|
|
* \todo [petri] Description.
|
|
*
|
|
* The functions for operating the hash are:
|
|
* \todo [petri] Figure out how to comment these in Doxygen-style.
|
|
*
|
|
* \todo [pyry] HashArray_find() will break if dePoolArray implementation changes.
|
|
*
|
|
* \code
|
|
* HashArray* HashArray_create (deMemPool* pool);
|
|
* int HashArray_getNumElements (const HashArray* hashArray);
|
|
* Value* HashArray_find (Hash* hashArray, Key key);
|
|
* deBool HashArray_insert (Hash* hashArray, Key key, Value value);
|
|
* deBool HashArray_copyToArray (Hash* hashArray, KeyArray* keys, ValueArray* values);
|
|
* \endcode
|
|
*//*--------------------------------------------------------------------*/
|
|
#define DE_DECLARE_POOL_HASH_ARRAY(TYPENAME, KEYTYPE, VALUETYPE, KEYARRAYTYPE, VALUEARRAYTYPE) \
|
|
\
|
|
DE_DECLARE_POOL_ARRAY(TYPENAME##Array, VALUETYPE); \
|
|
DE_DECLARE_POOL_HASH(TYPENAME##Hash, KEYTYPE, int); \
|
|
\
|
|
typedef struct TYPENAME_s \
|
|
{ \
|
|
TYPENAME##Hash* hash; \
|
|
TYPENAME##Array* array; \
|
|
} TYPENAME; /* NOLINT(TYPENAME) */ \
|
|
\
|
|
TYPENAME* TYPENAME##_create (deMemPool* pool); \
|
|
deBool TYPENAME##_insert (DE_PTR_TYPE(TYPENAME) hashArray, KEYTYPE key, VALUETYPE value); \
|
|
deBool TYPENAME##_copyToArray (const TYPENAME* hashArray, DE_PTR_TYPE(KEYARRAYTYPE) keys, DE_PTR_TYPE(VALUEARRAYTYPE) values); \
|
|
\
|
|
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* hashArray) DE_UNUSED_FUNCTION; \
|
|
DE_INLINE VALUETYPE* TYPENAME##_find (const TYPENAME* hashArray, KEYTYPE key) DE_UNUSED_FUNCTION; \
|
|
DE_INLINE void TYPENAME##_reset (DE_PTR_TYPE(TYPENAME) hashArray) DE_UNUSED_FUNCTION; \
|
|
\
|
|
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* hashArray) \
|
|
{ \
|
|
return TYPENAME##Array_getNumElements(hashArray->array); \
|
|
} \
|
|
\
|
|
DE_INLINE VALUETYPE* TYPENAME##_find (const TYPENAME* hashArray, KEYTYPE key) \
|
|
{ \
|
|
int* ndxPtr = TYPENAME##Hash_find(hashArray->hash, key); \
|
|
if (!ndxPtr) \
|
|
return DE_NULL; \
|
|
else \
|
|
{ \
|
|
int ndx = *ndxPtr; \
|
|
DE_ASSERT(ndx >= 0 && ndx < hashArray->array->numElements); \
|
|
{ \
|
|
int pageNdx = (ndx >> DE_ARRAY_ELEMENTS_PER_PAGE_LOG2); \
|
|
int subNdx = ndx & ((1 << DE_ARRAY_ELEMENTS_PER_PAGE_LOG2) - 1); \
|
|
return &((VALUETYPE*)hashArray->array->pageTable[pageNdx])[subNdx]; \
|
|
} \
|
|
} \
|
|
} \
|
|
\
|
|
DE_INLINE void TYPENAME##_reset (DE_PTR_TYPE(TYPENAME) hashArray) \
|
|
{ \
|
|
TYPENAME##Hash_reset(hashArray->hash); \
|
|
TYPENAME##Array_reset(hashArray->array); \
|
|
} \
|
|
\
|
|
struct TYPENAME##Dummy_s { int dummy; }
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Implement a template pool hash-array class.
|
|
* \param TYPENAME Type name of the declared hash.
|
|
* \param KEYTYPE Type of the key.
|
|
* \param VALUETYPE Type of the value.
|
|
* \param KEYARRAYTYPE Type of the key array.
|
|
* \param VALUEARRAYTYPE Type of the value array.
|
|
* \param HASHFUNC Function used for hashing the key.
|
|
* \param CMPFUNC Function used for exact matching of the keys.
|
|
*
|
|
* This macro has implements the hash declared with DE_DECLARE_POOL_HASH.
|
|
* Usually this macro should be used from a .c file, since the macro expands
|
|
* into multiple functions. The TYPENAME, KEYTYPE, and VALUETYPE parameters
|
|
* must match those of the declare macro.
|
|
*//*--------------------------------------------------------------------*/
|
|
#define DE_IMPLEMENT_POOL_HASH_ARRAY(TYPENAME, KEYTYPE, VALUETYPE, KEYARRAYTYPE, VALUEARRAYTYPE, KEYHASHFUNC, KEYCMPFUNC) \
|
|
\
|
|
DE_IMPLEMENT_POOL_HASH(TYPENAME##Hash, KEYTYPE, int, KEYHASHFUNC, KEYCMPFUNC); \
|
|
\
|
|
TYPENAME* TYPENAME##_create (deMemPool* pool) \
|
|
{ \
|
|
DE_PTR_TYPE(TYPENAME) hashArray = DE_POOL_NEW(pool, TYPENAME); \
|
|
if (!hashArray) return DE_NULL; \
|
|
if ((hashArray->hash = TYPENAME##Hash_create(pool)) == DE_NULL) \
|
|
return DE_NULL; \
|
|
if ((hashArray->array = TYPENAME##Array_create(pool)) == DE_NULL) \
|
|
return DE_NULL; \
|
|
return hashArray; \
|
|
} \
|
|
\
|
|
deBool TYPENAME##_insert (DE_PTR_TYPE(TYPENAME) hashArray, KEYTYPE key, VALUETYPE value) \
|
|
{ \
|
|
int numElements = TYPENAME##Array_getNumElements(hashArray->array); \
|
|
DE_ASSERT(TYPENAME##Hash_getNumElements(hashArray->hash) == numElements); \
|
|
DE_ASSERT(!TYPENAME##Hash_find(hashArray->hash, key)); \
|
|
if (!TYPENAME##Array_setSize(hashArray->array, numElements+1) || \
|
|
!TYPENAME##Hash_insert(hashArray->hash, key, numElements)) \
|
|
return DE_FALSE; \
|
|
TYPENAME##Array_set(hashArray->array, numElements, value); \
|
|
return DE_TRUE; \
|
|
} \
|
|
\
|
|
deBool TYPENAME##_copyToArray (const TYPENAME* hashArray, DE_PTR_TYPE(KEYARRAYTYPE) keys, DE_PTR_TYPE(VALUEARRAYTYPE) values) \
|
|
{ \
|
|
int numElements = TYPENAME##Array_getNumElements(hashArray->array); \
|
|
TYPENAME##Hash* hash = hashArray->hash; \
|
|
TYPENAME##HashIter iter; \
|
|
DE_ASSERT(TYPENAME##Hash_getNumElements(hashArray->hash) == numElements); \
|
|
if ((keys && !KEYARRAYTYPE##_setSize(keys, numElements)) || \
|
|
(values && !VALUEARRAYTYPE##_setSize(values, numElements))) \
|
|
return DE_FALSE; \
|
|
for (TYPENAME##HashIter_init(hash, &iter); TYPENAME##HashIter_hasItem(&iter); TYPENAME##HashIter_next(&iter)) \
|
|
{ \
|
|
KEYTYPE key = TYPENAME##HashIter_getKey(&iter); \
|
|
int ndx = TYPENAME##HashIter_getValue(&iter); \
|
|
if (keys) KEYARRAYTYPE##_set(keys, ndx, key); \
|
|
if (values) VALUEARRAYTYPE##_set(values, ndx, TYPENAME##Array_get(hashArray->array, ndx)); \
|
|
} \
|
|
return DE_TRUE; \
|
|
} \
|
|
\
|
|
struct TYPENAME##Dummy2_s { int dummy; }
|
|
|
|
#endif /* _DEPOOLHASHARRAY_H */
|