1/*---------------------------------------------------------------------------*
2 *  Int8ArrayListImpl.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 "Int8ArrayList.h"
21#include "Int8ArrayListImpl.h"
22#include "pmemory.h"
23#include "passert.h"
24
25#define MTAG NULL
26#define INITIAL_SIZE 32
27
28
29ESR_ReturnCode Int8ArrayListCreate(Int8ArrayList** self)
30{
31  Int8ArrayListImpl* impl;
32
33  if (self == NULL)
34    return ESR_INVALID_ARGUMENT;
35  impl = NEW(Int8ArrayListImpl, MTAG);
36  if (impl == NULL)
37    return ESR_OUT_OF_MEMORY;
38  impl->Interface.add = &Int8ArrayList_Add;
39  impl->Interface.contains = &Int8ArrayList_Contains;
40  impl->Interface.destroy = &Int8ArrayList_Destroy;
41  impl->Interface.get = &Int8ArrayList_Get;
42  impl->Interface.getSize = &Int8ArrayList_GetSize;
43  impl->Interface.remove = &Int8ArrayList_Remove;
44  impl->Interface.removeAll = &Int8ArrayList_RemoveAll;
45  impl->Interface.set = &Int8ArrayList_Set;
46  impl->Interface.toStaticArray = &Int8ArrayList_ToStaticArray;
47  impl->Interface.clone = &Int8ArrayList_Clone;
48  impl->contents = MALLOC((INITIAL_SIZE + 1) * sizeof(asr_int8_t), MTAG);
49  if (impl->contents == NULL)
50  {
51    FREE(impl);
52    return ESR_OUT_OF_MEMORY;
53  }
54  impl->actualSize = INITIAL_SIZE;
55  impl->virtualSize = 0;
56  *self = (Int8ArrayList*) impl;
57  return ESR_SUCCESS;
58}
59
60ESR_ReturnCode Int8ArrayListImport(asr_int8_t* value, Int8ArrayList** self)
61{
62  ESR_ReturnCode rc;
63  Int8ArrayListImpl* impl;
64
65  if (self == NULL)
66    return ESR_INVALID_ARGUMENT;
67  CHK(rc, Int8ArrayListCreate(self));
68  impl = (Int8ArrayListImpl*) self;
69  impl->contents = value;
70  return ESR_SUCCESS;
71CLEANUP:
72  return rc;
73}
74
75ESR_ReturnCode Int8ArrayList_Add(Int8ArrayList* self, const asr_int8_t element)
76{
77  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
78
79  if (impl->virtualSize >= impl->actualSize)
80  {
81    /* enlarge buffer */
82    asr_int8_t* temp = REALLOC(impl->contents, (impl->actualSize * 2 + 1) * sizeof(asr_int8_t));
83    if (temp == NULL)
84      return ESR_OUT_OF_MEMORY;
85    impl->contents = temp;
86    impl->actualSize *= 2;
87  }
88  impl->contents[impl->virtualSize] = element;
89  ++impl->virtualSize;
90  return ESR_SUCCESS;
91}
92
93ESR_ReturnCode Int8ArrayList_Remove(Int8ArrayList* self, const asr_int8_t element)
94{
95  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
96  asr_int8_t* contents = impl->contents; /* cache pointer */
97  size_t virtualSize = impl->virtualSize; /* cache value */
98  size_t i;
99
100  for (i = 0; i < virtualSize; ++i)
101  {
102    if (contents[i] == element)
103    {
104      --virtualSize;
105      break;
106    }
107  }
108  /* shift remaining elements back */
109  for (; i < virtualSize; ++i)
110    contents[i] = contents[i+1];
111
112  impl->virtualSize = virtualSize; /* flush cache */
113  if (virtualSize <= impl->actualSize / 4)
114  {
115    /* shrink buffer */
116    impl->contents = REALLOC(contents, (impl->actualSize / 2 + 1) * sizeof(asr_int8_t));
117    passert(impl->contents != NULL); /* should never fail */
118    impl->actualSize /= 2;
119  }
120  return ESR_SUCCESS;
121}
122
123ESR_ReturnCode Int8ArrayList_RemoveAll(Int8ArrayList* self)
124{
125  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
126
127  impl->virtualSize = 0;
128  return ESR_SUCCESS;
129}
130
131ESR_ReturnCode Int8ArrayList_Contains(Int8ArrayList* self, const asr_int8_t element, ESR_BOOL* exists)
132{
133  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
134  size_t i;
135  size_t virtualSize = impl->virtualSize; /* cache value */
136  asr_int8_t* contents = impl->contents; /* cache value */
137
138  for (i = 0; i < virtualSize; ++i)
139  {
140    if (contents[i] == element)
141    {
142      *exists = ESR_TRUE;
143      return ESR_SUCCESS;
144    }
145  }
146  *exists = ESR_FALSE;
147  return ESR_SUCCESS;
148}
149
150ESR_ReturnCode Int8ArrayList_Get(Int8ArrayList* self, size_t index, asr_int8_t* element)
151{
152  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
153
154  passert(index >= 0 && index <= impl->virtualSize);
155  *element = impl->contents[index];
156  return ESR_SUCCESS;
157}
158
159ESR_ReturnCode Int8ArrayList_Set(Int8ArrayList* self, size_t index, const asr_int8_t element)
160{
161  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
162
163  passert(index >= 0 && index <= impl->virtualSize);
164  impl->contents[index] = element;
165  return ESR_SUCCESS;
166}
167
168ESR_ReturnCode Int8ArrayList_GetSize(Int8ArrayList* self, size_t* size)
169{
170  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
171
172  *size = impl->virtualSize;
173  return ESR_SUCCESS;
174}
175
176ESR_ReturnCode Int8ArrayList_ToStaticArray(Int8ArrayList* self, asr_int8_t** newArray)
177{
178  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
179
180  *newArray = impl->contents;
181  impl->contents = NULL; /* prevent free() from deallocating buffer */
182  return Int8ArrayList_Destroy(self);
183}
184
185ESR_ReturnCode Int8ArrayList_Clone(Int8ArrayList* self, Int8ArrayList* clone)
186{
187  size_t size, i;
188  asr_int8_t element;
189  ESR_ReturnCode rc;
190
191  CHK(rc, clone->removeAll(clone));
192  CHK(rc, self->getSize(self, &size));
193  for (i = 0; i < size; ++i)
194  {
195    CHK(rc, self->get(self, i, &element));
196    CHK(rc, clone->add(clone, element));
197  }
198  return ESR_SUCCESS;
199CLEANUP:
200  return rc;
201}
202
203ESR_ReturnCode Int8ArrayList_Destroy(Int8ArrayList* self)
204{
205  Int8ArrayListImpl* impl = (Int8ArrayListImpl*) self;
206
207  FREE(impl->contents);
208  FREE(impl);
209  return ESR_SUCCESS;
210}
211