blob: f28a70c688c0ad4a86f92373a592ae4bffec874f [file] [log] [blame]
Sharvil Nanavatibadeb922014-11-13 17:29:21 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2014 Google, Inc.
Sharvil Nanavatibadeb922014-11-13 17:29:21 -08004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
Chris Mantonf8027002015-03-12 09:22:48 -070019#define LOG_TAG "bt_osi_array"
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080020
Marie Janssen49a86702015-07-08 11:48:57 -070021#include "osi/include/array.h"
22
Jack Hef2af1c42016-12-13 01:59:12 -080023#include <base/logging.h>
Etan Cohen3e59b5b2015-03-31 17:15:53 -070024#include <stdlib.h>
25#include <string.h>
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080026
Sharvil Nanavati0f9b91e2015-03-12 15:42:50 -070027#include "osi/include/allocator.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080028#include "osi/include/log.h"
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080029
30struct array_t {
31 size_t element_size;
32 size_t length;
33 size_t capacity;
Myles Watsonb55040c2016-10-19 13:15:34 -070034 uint8_t* data;
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080035 uint8_t internal_storage[];
36};
37
Myles Watsonb55040c2016-10-19 13:15:34 -070038static bool grow(array_t* array);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080039
40static const size_t INTERNAL_ELEMENTS = 16;
41
Myles Watsonb55040c2016-10-19 13:15:34 -070042array_t* array_new(size_t element_size) {
Jack Hef2af1c42016-12-13 01:59:12 -080043 CHECK(element_size > 0);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080044
Myles Watsonb55040c2016-10-19 13:15:34 -070045 array_t* array = static_cast<array_t*>(
46 osi_calloc(sizeof(array_t) + element_size * INTERNAL_ELEMENTS));
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080047
48 array->element_size = element_size;
49 array->capacity = INTERNAL_ELEMENTS;
50 array->data = array->internal_storage;
51 return array;
52}
53
Myles Watsonb55040c2016-10-19 13:15:34 -070054void array_free(array_t* array) {
55 if (!array) return;
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080056
Myles Watsonb55040c2016-10-19 13:15:34 -070057 if (array->data != array->internal_storage) free(array->data);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080058
59 osi_free(array);
60}
61
Myles Watsonb55040c2016-10-19 13:15:34 -070062void* array_ptr(const array_t* array) { return array_at(array, 0); }
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080063
Myles Watsonb55040c2016-10-19 13:15:34 -070064void* array_at(const array_t* array, size_t index) {
Jack Hef2af1c42016-12-13 01:59:12 -080065 CHECK(array != NULL);
66 CHECK(index < array->length);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080067 return array->data + (index * array->element_size);
68}
69
Myles Watsonb55040c2016-10-19 13:15:34 -070070size_t array_length(const array_t* array) {
Jack Hef2af1c42016-12-13 01:59:12 -080071 CHECK(array != NULL);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080072 return array->length;
73}
74
Myles Watsonb55040c2016-10-19 13:15:34 -070075bool array_append_value(array_t* array, uint32_t value) {
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080076 return array_append_ptr(array, &value);
77}
78
Myles Watsonb55040c2016-10-19 13:15:34 -070079bool array_append_ptr(array_t* array, void* data) {
Jack Hef2af1c42016-12-13 01:59:12 -080080 CHECK(array != NULL);
81 CHECK(data != NULL);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080082
83 if (array->length == array->capacity && !grow(array)) {
Myles Watsonb55040c2016-10-19 13:15:34 -070084 LOG_ERROR(LOG_TAG,
85 "%s unable to grow array past current capacity of %zu elements "
86 "of size %zu.",
87 __func__, array->capacity, array->element_size);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080088 return false;
89 }
90
91 ++array->length;
92 memcpy(array_at(array, array->length - 1), data, array->element_size);
93 return true;
94}
95
Myles Watsonb55040c2016-10-19 13:15:34 -070096static bool grow(array_t* array) {
Sharvil Nanavatibadeb922014-11-13 17:29:21 -080097 const size_t new_capacity = array->capacity + (array->capacity / 2);
98 const bool is_moving = (array->data == array->internal_storage);
99
Myles Watsonb55040c2016-10-19 13:15:34 -0700100 void* new_data = realloc(is_moving ? NULL : array->data,
101 new_capacity * array->element_size);
102 if (!new_data) return false;
Sharvil Nanavatibadeb922014-11-13 17:29:21 -0800103
104 if (is_moving)
Myles Watsonb55040c2016-10-19 13:15:34 -0700105 memcpy(new_data, array->internal_storage,
106 array->length * array->element_size);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -0800107
Myles Watsonb55040c2016-10-19 13:15:34 -0700108 array->data = static_cast<uint8_t*>(new_data);
Sharvil Nanavatibadeb922014-11-13 17:29:21 -0800109 array->capacity = new_capacity;
110 return true;
111}