mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add array list structure.
Change hash table to use array lists instead of linked lists.
This commit is contained in:
parent
2c86712e21
commit
a251bf5d6f
137
src/libintstructs/array-list.c
Normal file
137
src/libintstructs/array-list.c
Normal 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);
|
||||
}
|
||||
34
src/libintstructs/array-list.h
Normal file
34
src/libintstructs/array-list.h
Normal 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 */
|
||||
136
src/libintstructs/hash-table.c
Normal file
136
src/libintstructs/hash-table.c
Normal 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);
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user