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
29ESR_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
59ESR_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;
70CLEANUP:
71  return rc;
72}
73
74ESR_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
92ESR_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
122ESR_ReturnCode IntArrayList_RemoveAll(IntArrayList* self)
123{
124  IntArrayListImpl* impl = (IntArrayListImpl*) self;
125
126  impl->virtualSize = 0;
127  return ESR_SUCCESS;
128}
129
130ESR_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
149ESR_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
158ESR_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
167ESR_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
175ESR_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
184ESR_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