/*---------------------------------------------------------------------------* * Int8ArrayListImpl.c * * * * Copyright 2007, 2008 Nuance Communciations, Inc. * * * * 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 "Int8ArrayList.h" #include "Int8ArrayListImpl.h" #include "pmemory.h" #include "passert.h" #define MTAG NULL #define INITIAL_SIZE 32 ESR_ReturnCode Int8ArrayListCreate(Int8ArrayList** self) { Int8ArrayListImpl* impl; if (self == NULL) return ESR_INVALID_ARGUMENT; impl = NEW(Int8ArrayListImpl, MTAG); if (impl == NULL) return ESR_OUT_OF_MEMORY; impl->Interface.add = &Int8ArrayList_Add; impl->Interface.contains = &Int8ArrayList_Contains; impl->Interface.destroy = &Int8ArrayList_Destroy; impl->Interface.get = &Int8ArrayList_Get; impl->Interface.getSize = &Int8ArrayList_GetSize; impl->Interface.remove = &Int8ArrayList_Remove; impl->Interface.removeAll = &Int8ArrayList_RemoveAll; impl->Interface.set = &Int8ArrayList_Set; impl->Interface.toStaticArray = &Int8ArrayList_ToStaticArray; impl->Interface.clone = &Int8ArrayList_Clone; impl->contents = MALLOC((INITIAL_SIZE + 1) * sizeof(asr_int8_t), MTAG); if (impl->contents == NULL) { FREE(impl); return ESR_OUT_OF_MEMORY; } impl->actualSize = INITIAL_SIZE; impl->virtualSize = 0; *self = (Int8ArrayList*) impl; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayListImport(asr_int8_t* value, Int8ArrayList** self) { ESR_ReturnCode rc; Int8ArrayListImpl* impl; if (self == NULL) return ESR_INVALID_ARGUMENT; CHK(rc, Int8ArrayListCreate(self)); impl = (Int8ArrayListImpl*) self; impl->contents = value; return ESR_SUCCESS; CLEANUP: return rc; } ESR_ReturnCode Int8ArrayList_Add(Int8ArrayList* self, const asr_int8_t element) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; if (impl->virtualSize >= impl->actualSize) { /* enlarge buffer */ asr_int8_t* temp = REALLOC(impl->contents, (impl->actualSize * 2 + 1) * sizeof(asr_int8_t)); if (temp == NULL) return ESR_OUT_OF_MEMORY; impl->contents = temp; impl->actualSize *= 2; } impl->contents[impl->virtualSize] = element; ++impl->virtualSize; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_Remove(Int8ArrayList* self, const asr_int8_t element) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; asr_int8_t* contents = impl->contents; /* cache pointer */ size_t virtualSize = impl->virtualSize; /* cache value */ size_t i; for (i = 0; i < virtualSize; ++i) { if (contents[i] == element) { --virtualSize; break; } } /* shift remaining elements back */ for (; i < virtualSize; ++i) contents[i] = contents[i+1]; impl->virtualSize = virtualSize; /* flush cache */ if (virtualSize <= impl->actualSize / 4) { /* shrink buffer */ impl->contents = REALLOC(contents, (impl->actualSize / 2 + 1) * sizeof(asr_int8_t)); passert(impl->contents != NULL); /* should never fail */ impl->actualSize /= 2; } return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_RemoveAll(Int8ArrayList* self) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; impl->virtualSize = 0; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_Contains(Int8ArrayList* self, const asr_int8_t element, ESR_BOOL* exists) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; size_t i; size_t virtualSize = impl->virtualSize; /* cache value */ asr_int8_t* contents = impl->contents; /* cache value */ for (i = 0; i < virtualSize; ++i) { if (contents[i] == element) { *exists = ESR_TRUE; return ESR_SUCCESS; } } *exists = ESR_FALSE; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_Get(Int8ArrayList* self, size_t index, asr_int8_t* element) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; passert(index >= 0 && index <= impl->virtualSize); *element = impl->contents[index]; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_Set(Int8ArrayList* self, size_t index, const asr_int8_t element) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; passert(index >= 0 && index <= impl->virtualSize); impl->contents[index] = element; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_GetSize(Int8ArrayList* self, size_t* size) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; *size = impl->virtualSize; return ESR_SUCCESS; } ESR_ReturnCode Int8ArrayList_ToStaticArray(Int8ArrayList* self, asr_int8_t** newArray) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; *newArray = impl->contents; impl->contents = NULL; /* prevent free() from deallocating buffer */ return Int8ArrayList_Destroy(self); } ESR_ReturnCode Int8ArrayList_Clone(Int8ArrayList* self, Int8ArrayList* clone) { size_t size, i; asr_int8_t element; ESR_ReturnCode rc; CHK(rc, clone->removeAll(clone)); CHK(rc, self->getSize(self, &size)); for (i = 0; i < size; ++i) { CHK(rc, self->get(self, i, &element)); CHK(rc, clone->add(clone, element)); } return ESR_SUCCESS; CLEANUP: return rc; } ESR_ReturnCode Int8ArrayList_Destroy(Int8ArrayList* self) { Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self; FREE(impl->contents); FREE(impl); return ESR_SUCCESS; }