1 /*---------------------------------------------------------------------------* 2 * IntArrayListImpl.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 #include "IntArrayList.h" 21 #include "IntArrayListImpl.h" 22 #include "pmemory.h" 23 #include "passert.h" 24 25 #define MTAG NULL 26 #define INITIAL_SIZE 32 27 28 29 ESR_ReturnCode IntArrayListCreate(IntArrayList** self) 30 { 31 IntArrayListImpl* impl; 32 33 if (self == NULL) 34 return ESR_INVALID_ARGUMENT; 35 impl = NEW(IntArrayListImpl, MTAG); 36 if (impl == NULL) 37 return ESR_OUT_OF_MEMORY; 38 impl->Interface.add = &IntArrayList_Add; 39 impl->Interface.contains = &IntArrayList_Contains; 40 impl->Interface.destroy = &IntArrayList_Destroy; 41 impl->Interface.get = &IntArrayList_Get; 42 impl->Interface.getSize = &IntArrayList_GetSize; 43 impl->Interface.remove = &IntArrayList_Remove; 44 impl->Interface.removeAll = &IntArrayList_RemoveAll; 45 impl->Interface.set = &IntArrayList_Set; 46 impl->Interface.toStaticArray = &IntArrayList_ToStaticArray; 47 impl->contents = MALLOC((INITIAL_SIZE + 1) * sizeof(int), MTAG); 48 if (impl->contents == NULL) 49 { 50 FREE(impl); 51 return ESR_OUT_OF_MEMORY; 52 } 53 impl->actualSize = INITIAL_SIZE; 54 impl->virtualSize = 0; 55 *self = (IntArrayList*) impl; 56 return ESR_SUCCESS; 57 } 58 59 ESR_ReturnCode IntArrayListImport(int* value, IntArrayList** self) 60 { 61 ESR_ReturnCode rc; 62 IntArrayListImpl* impl; 63 64 if (self == NULL) 65 return ESR_INVALID_ARGUMENT; 66 CHK(rc, IntArrayListCreate(self)); 67 impl = (IntArrayListImpl*) self; 68 impl->contents = value; 69 return ESR_SUCCESS; 70 CLEANUP: 71 return rc; 72 } 73 74 ESR_ReturnCode IntArrayList_Add(IntArrayList* self, const int element) 75 { 76 IntArrayListImpl* impl = (IntArrayListImpl*) self; 77 78 if (impl->virtualSize >= impl->actualSize) 79 { 80 /* enlarge buffer */ 81 int* temp = REALLOC(impl->contents, (impl->actualSize * 2 + 1) * sizeof(int)); 82 if (temp == NULL) 83 return ESR_OUT_OF_MEMORY; 84 impl->contents = temp; 85 impl->actualSize *= 2; 86 } 87 impl->contents[impl->virtualSize] = element; 88 ++impl->virtualSize; 89 return ESR_SUCCESS; 90 } 91 92 ESR_ReturnCode IntArrayList_Remove(IntArrayList* self, const int element) 93 { 94 IntArrayListImpl* impl = (IntArrayListImpl*) self; 95 int* contents = impl->contents; /* cache pointer */ 96 size_t virtualSize = impl->virtualSize; /* cache value */ 97 size_t i; 98 99 for (i = 0; i < virtualSize; ++i) 100 { 101 if (contents[i] == element) 102 { 103 --virtualSize; 104 break; 105 } 106 } 107 /* shift remaining elements back */ 108 for (; i < virtualSize; ++i) 109 contents[i] = contents[i+1]; 110 111 impl->virtualSize = virtualSize; /* flush cache */ 112 if (virtualSize <= impl->actualSize / 4) 113 { 114 /* shrink buffer */ 115 impl->contents = REALLOC(contents, (impl->actualSize / 2 + 1) * sizeof(int)); 116 passert(impl->contents != NULL); /* should never fail */ 117 impl->actualSize /= 2; 118 } 119 return ESR_SUCCESS; 120 } 121 122 ESR_ReturnCode IntArrayList_RemoveAll(IntArrayList* self) 123 { 124 IntArrayListImpl* impl = (IntArrayListImpl*) self; 125 126 impl->virtualSize = 0; 127 return ESR_SUCCESS; 128 } 129 130 ESR_ReturnCode IntArrayList_Contains(IntArrayList* self, const int element, ESR_BOOL* exists) 131 { 132 IntArrayListImpl* impl = (IntArrayListImpl*) self; 133 size_t i; 134 size_t virtualSize = impl->virtualSize; /* cache value */ 135 int* contents = impl->contents; /* cache value */ 136 137 for (i = 0; i < virtualSize; ++i) 138 { 139 if (contents[i] == element) 140 { 141 *exists = ESR_TRUE; 142 return ESR_SUCCESS; 143 } 144 } 145 *exists = ESR_FALSE; 146 return ESR_SUCCESS; 147 } 148 149 ESR_ReturnCode IntArrayList_Get(IntArrayList* self, size_t index, int* element) 150 { 151 IntArrayListImpl* impl = (IntArrayListImpl*) self; 152 153 passert(index >= 0 && index <= impl->virtualSize); 154 *element = impl->contents[index]; 155 return ESR_SUCCESS; 156 } 157 158 ESR_ReturnCode IntArrayList_Set(IntArrayList* self, size_t index, const int element) 159 { 160 IntArrayListImpl* impl = (IntArrayListImpl*) self; 161 162 passert(index >= 0 && index <= impl->virtualSize); 163 impl->contents[index] = element; 164 return ESR_SUCCESS; 165 } 166 167 ESR_ReturnCode IntArrayList_GetSize(IntArrayList* self, size_t* size) 168 { 169 IntArrayListImpl* impl = (IntArrayListImpl*) self; 170 171 *size = impl->virtualSize; 172 return ESR_SUCCESS; 173 } 174 175 ESR_ReturnCode IntArrayList_ToStaticArray(IntArrayList* self, int** newArray) 176 { 177 IntArrayListImpl* impl = (IntArrayListImpl*) self; 178 179 *newArray = impl->contents; 180 impl->contents = NULL; /* prevent free() from deallocating buffer */ 181 return IntArrayList_Destroy(self); 182 } 183 184 ESR_ReturnCode IntArrayList_Destroy(IntArrayList* self) 185 { 186 IntArrayListImpl* impl = (IntArrayListImpl*) self; 187 188 FREE(impl->contents); 189 FREE(impl); 190 return ESR_SUCCESS; 191 } 192