Add array list structure.

Change hash table to use array lists instead of linked lists.
This commit is contained in:
Ilmir Usmanov 2014-12-10 18:27:36 +03:00
parent 2c86712e21
commit a251bf5d6f
4 changed files with 314 additions and 86 deletions

View File

@ -0,0 +1,137 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* 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.
*/
#include "array-list.h"
#include "mem-heap.h"
#include "jerry-libc.h"
#define ARRAY_LIST_MAGIC 0x39
typedef struct
{
uint8_t magic;
uint8_t element_size;
size_t len;
size_t size;
}
array_list_header;
static array_list_header *
extract_header (array_list al)
{
JERRY_ASSERT (al != null_list);
array_list_header *header = (array_list_header *) al;
JERRY_ASSERT (header->magic == ARRAY_LIST_MAGIC);
return header;
}
static uint8_t *
data (array_list al)
{
return (uint8_t *) al + sizeof (array_list_header);
}
array_list
array_list_append (array_list al, void *element)
{
array_list_header *h = extract_header (al);
if ((h->len + 1) * h->element_size + sizeof (array_list_header) > h->size)
{
size_t size = mem_heap_recommend_allocation_size (h->size + h->element_size);
array_list_header *temp = (array_list_header *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM);
__memset (temp, 0, size);
__memcpy (temp, h, h->size);
temp->size = size;
mem_heap_free_block ((uint8_t *) h);
h = temp;
al = (array_list) h;
}
__memcpy (data (al) + (h->len * h->element_size), element, h->element_size);
h->len++;
return al;
}
void
array_list_drop_last (array_list al)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (h->len > 0);
h->len--;
}
void *
array_list_element (array_list al, size_t index)
{
array_list_header *h = extract_header (al);
if (h->len <= index)
{
return NULL;
}
return data (al) + (index * h->element_size);
}
void
array_list_set_element (array_list al, size_t index, void *elem)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (index < h->len);
__memcpy (data (al) + (index * h->element_size), elem, h->element_size);
}
void *
array_list_last_element (array_list al, size_t index)
{
array_list_header *h = extract_header (al);
if (index == 0 || index > h->len)
{
return NULL;
}
return array_list_element (al, (size_t) (h->len - index));
}
void
array_list_set_last_element (array_list al, size_t index, void *elem)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (index != 0 && index <= h->len);
array_list_set_element (al, (size_t) (h->len - index), elem);
}
array_list
array_list_init (uint8_t element_size)
{
size_t size = mem_heap_recommend_allocation_size (sizeof (array_list_header));
array_list_header *header = (array_list_header *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM);
__memset (header, 0, size);
header->magic = ARRAY_LIST_MAGIC;
header->element_size = element_size;
header->len = 0;
header->size = size;
return (array_list) header;
}
size_t
array_list_len (array_list al)
{
array_list_header *h = extract_header (al);
return h->len;
}
void
array_list_free (array_list al)
{
array_list_header *h = extract_header (al);
mem_heap_free_block ((uint8_t *) h);
}

View File

@ -0,0 +1,34 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* 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 ARRAY_LIST_H
#define ARRAY_LIST_H
#include "globals.h"
typedef uint8_t* array_list;
#define null_list NULL
array_list array_list_init (uint8_t);
void array_list_free (array_list);
array_list array_list_append (array_list, void *);
void array_list_drop_last (array_list);
void *array_list_element (array_list, size_t);
void array_list_set_element (array_list, size_t, void *);
void *array_list_last_element (array_list, size_t);
void array_list_set_last_element (array_list, size_t, void *);
size_t array_list_len (array_list);
#endif /* ARRAY_LIST_H */

View File

@ -0,0 +1,136 @@
/* Copyright 2014 Samsung Electronics Co., Ltd.
*
* 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.
*/
#include "hash-table.h"
#include "array-list.h"
#include "mem-heap.h"
#include "jerry-libc.h"
#define HASH_MAP_MAGIC 0x67
typedef struct
{
uint16_t (*hash) (void *);
array_list *data;
uint16_t size;
uint8_t magic;
uint8_t key_size;
uint8_t value_size;
mem_heap_alloc_term_t alloc_term;
}
hash_table_int;
static hash_table_int *
extract_header (hash_table ht)
{
JERRY_ASSERT (ht != null_hash);
hash_table_int *hti = (hash_table_int *) ht;
JERRY_ASSERT (hti->magic == HASH_MAP_MAGIC);
return hti;
}
static uint8_t
bucket_size (hash_table_int *hti)
{
return (uint8_t) (hti->key_size + hti->value_size);
}
static array_list
get_list (hash_table_int *h, uint16_t i)
{
return h->data[i];
}
static void
set_list (hash_table_int *h, uint16_t i, array_list al)
{
h->data[i] = al;
}
void
hash_table_insert (hash_table ht, void *key, void *value)
{
hash_table_int *hti = extract_header (ht);
uint16_t index = hti->hash (key);
JERRY_ASSERT (index < hti->size);
array_list list = get_list (hti, index);
if (list == null_list)
{
list = array_list_init (bucket_size (hti));
}
uint8_t *bucket = mem_heap_alloc_block (bucket_size (hti), hti->alloc_term);
__memcpy (bucket, key, hti->key_size);
__memcpy (bucket + hti->key_size, value, hti->value_size);
list = array_list_append (list, bucket);
hti->data[index] = list;
mem_heap_free_block (bucket);
}
void *
hash_table_lookup (hash_table ht, void *key)
{
JERRY_ASSERT (key != NULL);
hash_table_int *h = extract_header (ht);
uint16_t index = h->hash (key);
array_list al = get_list (h, index);
if (al == null_list)
{
return NULL;
}
for (uint16_t i = 0; i < array_list_len (al); i++)
{
uint8_t *bucket = array_list_element (al, i);
JERRY_ASSERT (bucket != NULL);
if (!__memcmp (bucket, key, h->key_size))
{
return bucket + h->key_size;
}
}
return NULL;
}
hash_table
hash_table_init (uint8_t key_size, uint8_t value_size, uint16_t size,
uint16_t (*hash) (void *), mem_heap_alloc_term_t alloc_term)
{
hash_table_int *res = (hash_table_int *) mem_heap_alloc_block (sizeof (hash_table_int), alloc_term);
__memset (res, 0, sizeof (hash_table_int));
res->magic = HASH_MAP_MAGIC;
res->key_size = key_size;
res->value_size = value_size;
res->size = size;
res->alloc_term = alloc_term;
res->data = (array_list *) mem_heap_alloc_block (size * sizeof (array_list), alloc_term);
__memset (res->data, 0, size * sizeof (array_list));
res->hash = hash;
return res;
}
void
hash_table_free (hash_table ht)
{
hash_table_int *h = extract_header (ht);
for (uint16_t i = 0; i < h->size; i++)
{
array_list al = get_list (h, i);
if (al != null_list)
{
array_list_free (al);
set_list (h, i, null_list);
}
}
mem_heap_free_block ((uint8_t *) h->data);
mem_heap_free_block ((uint8_t *) h);
}

View File

@ -27,93 +27,14 @@
#define HASH_TABLE_H
#include "linked-list.h"
#include "mem-heap.h"
#define DEFINE_BACKET_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
KEY_TYPE key; \
VALUE_TYPE value; \
} \
NAME##_backet;
typedef void* hash_table;
#define null_hash NULL
TODO (/*Rewrite to NAME##_backet **backets when neccesary*/)
#define DEFINE_HASH_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
NAME##_backet *backets; \
uint8_t *lens; \
uint8_t size; \
uint8_t max_lens; \
} \
NAME##_hash_table;
#define HASH_INIT(NAME, SIZE) \
do { \
NAME.size = SIZE; \
size_t backets_size = mem_heap_recommend_allocation_size (SIZE * sizeof (NAME##_backet)); \
size_t lens_size = mem_heap_recommend_allocation_size (SIZE); \
NAME.backets = (NAME##_backet *) mem_heap_alloc_block (backets_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME.lens = mem_heap_alloc_block (lens_size, MEM_HEAP_ALLOC_SHORT_TERM); \
__memset (NAME.backets, 0, SIZE); \
__memset (NAME.lens, 0, SIZE); \
NAME.max_lens = 1; \
} while (0);
#define HASH_FREE(NAME) \
do { \
mem_heap_free_block ((uint8_t *) NAME.backets); \
mem_heap_free_block (NAME.lens); \
} while (0)
#define DEFINE_HASH_INSERT(NAME, KEY_TYPE, VALUE_TYPE) \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) __unused; \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) { \
NAME##_backet backet = (NAME##_backet) { .key = key, .value = value }; \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
JERRY_ASSERT (NAME.backets != NULL); \
JERRY_ASSERT (NAME.lens[hash] == 0); \
NAME.backets[hash] = backet; \
NAME.lens[hash] = 1; \
}
#define HASH_INSERT(NAME, KEY, VALUE) \
do { \
hash_insert_##NAME (KEY, VALUE); \
} while (0)
#define DEFINE_HASH_LOOKUP(NAME, KEY_TYPE, VALUE_TYPE) \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) __unused; \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) \
{ \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
if (NAME.lens[hash] == 0) \
{ \
return NULL; \
} \
if (KEY_TYPE##_equal (NAME.backets[hash].key, key)) \
{ \
return &NAME.backets[hash].value; \
} \
return NULL; \
}
#define HASH_LOOKUP(NAME, KEY) \
lookup_##NAME (KEY)
#define HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
#define STATIC_HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
static NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
hash_table hash_table_init (uint8_t, uint8_t, uint16_t, uint16_t (*hash) (void *), mem_heap_alloc_term_t);
void hash_table_free (hash_table);
void hash_table_insert (hash_table, void *, void *);
void *hash_table_lookup (hash_table, void *);
#endif /* HASH_TABLE_H */