array.c revision 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <cutils/array.h>
18#include <assert.h>
19#include <stdlib.h>
20#include <string.h>
21
22#define INITIAL_CAPACITY (4)
23
24struct Array {
25    void** contents;
26    int size;
27    int capacity;
28};
29
30Array* arrayCreate() {
31    return calloc(1, sizeof(struct Array));
32}
33
34void arrayFree(Array* array) {
35    assert(array != NULL);
36
37    // Free internal array.
38    free(array->contents);
39
40    // Free the Array itself.
41    free(array);
42}
43
44/** Returns 0 if successful, < 0 otherwise.. */
45static int ensureCapacity(Array* array, int capacity) {
46    int oldCapacity = array->capacity;
47    if (capacity > oldCapacity) {
48        int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity * 2;
49
50        // Keep doubling capacity until we surpass necessary capacity.
51        while (newCapacity < capacity) {
52            newCapacity *= 2;
53        }
54
55        void** newContents;
56        if (array->contents == NULL) {
57            // Allocate new array.
58            newContents = malloc(newCapacity * sizeof(void*));
59            if (newContents == NULL) {
60                return -1;
61            }
62        } else {
63            // Expand existing array.
64            newContents = realloc(array->contents, sizeof(void*) * newCapacity);
65            if (newContents == NULL) {
66                return -1;
67            }
68        }
69
70        array->capacity = newCapacity;
71        array->contents = newContents;
72    }
73
74    return 0;
75}
76
77int arrayAdd(Array* array, void* pointer) {
78    assert(array != NULL);
79    int size = array->size;
80    int result = ensureCapacity(array, size + 1);
81    if (result < 0) {
82        return result;
83    }
84    array->contents[size] = pointer;
85    array->size++;
86    return 0;
87}
88
89static inline void checkBounds(Array* array, int index) {
90    assert(array != NULL);
91    assert(index < array->size);
92    assert(index >= 0);
93}
94
95void* arrayGet(Array* array, int index) {
96    checkBounds(array, index);
97    return array->contents[index];
98}
99
100void* arrayRemove(Array* array, int index) {
101    checkBounds(array, index);
102
103    void* pointer = array->contents[index];
104
105    int newSize = array->size - 1;
106
107    // Shift entries left.
108    if (index != newSize) {
109        memmove(array->contents + index, array->contents + index + 1,
110                (sizeof(void*)) * (newSize - index));
111    }
112
113    array->size = newSize;
114
115    return pointer;
116}
117
118void* arraySet(Array* array, int index, void* pointer) {
119    checkBounds(array, index);
120    void* old = array->contents[index];
121    array->contents[index] = pointer;
122    return old;
123}
124
125int arraySetSize(Array* array, int newSize) {
126    assert(array != NULL);
127    assert(newSize >= 0);
128
129    int oldSize = array->size;
130
131    if (newSize > oldSize) {
132        // Expand.
133        int result = ensureCapacity(array, newSize);
134        if (result < 0) {
135            return result;
136        }
137
138        // Zero out new entries.
139        memset(array->contents + sizeof(void*) * oldSize, 0,
140                sizeof(void*) * (newSize - oldSize));
141    }
142
143    array->size = newSize;
144
145    return 0;
146}
147
148int arraySize(Array* array) {
149    assert(array != NULL);
150    return array->size;
151}
152
153const void** arrayUnwrap(Array* array) {
154    return array->contents;
155}
156