/* 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 "linked-list.h" #include "jerry-libc.h" #include "globals.h" #include "mem-heap.h" #include "lp-string.h" #define ASSERT_LIST(list) \ do { \ linked_list_header *header = (linked_list_header *) list; \ JERRY_ASSERT (header); \ JERRY_ASSERT (header->magic == LINKED_LIST_MAGIC); \ } while (0); linked_list linked_list_init (size_t element_size) { size_t size = mem_heap_recommend_allocation_size (element_size); linked_list list = mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM); if (list == null_list) { __printf ("Out of memory"); JERRY_UNREACHABLE (); } __memset (list, 0, size); linked_list_header* header = (linked_list_header *) list; header->magic = LINKED_LIST_MAGIC; header->prev = header->next = null_list; header->block_size = (uint8_t) (size - sizeof (linked_list_header)); return list; } void linked_list_free (linked_list list) { ASSERT_LIST (list); linked_list_header *header = (linked_list_header *) list; if (header->next) { linked_list_free ((linked_list) header->next); } mem_heap_free_block (list); } void * linked_list_element (linked_list list, size_t element_size, size_t element_num) { ASSERT_LIST (list); linked_list_header *header = (linked_list_header *) list; linked_list raw = list + sizeof (linked_list_header); if (header->block_size < element_size * (element_num + 1)) { if (header->next) { return linked_list_element ((linked_list) header->next, element_size, element_num - (header->block_size / element_size)); } else { return NULL; } } raw += element_size * element_num; return raw; } void linked_list_set_element (linked_list list, size_t element_size, size_t element_num, void *element) { ASSERT_LIST (list); linked_list_header *header = (linked_list_header *) list; linked_list raw = list + sizeof (linked_list_header); if (header->block_size < element_size * (element_num + 1)) { if (header->next == null_list) { header->next = (linked_list_header *) linked_list_init (element_size); header->next->prev = header; } linked_list_set_element ((linked_list) header->next, element_size, element_num - (header->block_size / element_size), element); return; } if (element == NULL) { return; } switch (element_size) { case 1: { ((uint8_t *) raw)[element_num] = *((uint8_t *) element); break; } case 2: { ((uint16_t *) raw)[element_num] = *((uint16_t *) element); break; } case 4: { ((uint32_t *) raw)[element_num] = *((uint32_t *) element); break; } case 8: { ((uint64_t *) raw)[element_num] = *((uint64_t *) element); break; } default: { __memcpy ((uint8_t*) raw + element_num * element_size, element, element_size); break; } } }