1226031Sstas/*
2226031Sstas * Copyright (c) 2010 Kungliga Tekniska H��gskolan
3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4226031Sstas * All rights reserved.
5226031Sstas *
6226031Sstas * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
7226031Sstas *
8226031Sstas * Redistribution and use in source and binary forms, with or without
9226031Sstas * modification, are permitted provided that the following conditions
10226031Sstas * are met:
11226031Sstas *
12226031Sstas * 1. Redistributions of source code must retain the above copyright
13226031Sstas *    notice, this list of conditions and the following disclaimer.
14226031Sstas *
15226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
16226031Sstas *    notice, this list of conditions and the following disclaimer in the
17226031Sstas *    documentation and/or other materials provided with the distribution.
18226031Sstas *
19226031Sstas * 3. Neither the name of the Institute nor the names of its contributors
20226031Sstas *    may be used to endorse or promote products derived from this software
21226031Sstas *    without specific prior written permission.
22226031Sstas *
23226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33226031Sstas * SUCH DAMAGE.
34226031Sstas */
35226031Sstas
36226031Sstas#include "baselocl.h"
37226031Sstas
38226031Sstas/*
39226031Sstas *
40226031Sstas */
41226031Sstas
42226031Sstasstruct heim_array_data {
43226031Sstas    size_t len;
44226031Sstas    heim_object_t *val;
45226031Sstas};
46226031Sstas
47226031Sstasstatic void
48226031Sstasarray_dealloc(heim_object_t ptr)
49226031Sstas{
50226031Sstas    heim_array_t array = ptr;
51226031Sstas    size_t n;
52226031Sstas    for (n = 0; n < array->len; n++)
53226031Sstas	heim_release(array->val[n]);
54226031Sstas    free(array->val);
55226031Sstas}
56226031Sstas
57226031Sstasstruct heim_type_data array_object = {
58226031Sstas    HEIM_TID_ARRAY,
59226031Sstas    "dict-object",
60226031Sstas    NULL,
61226031Sstas    array_dealloc,
62226031Sstas    NULL,
63226031Sstas    NULL,
64226031Sstas    NULL
65226031Sstas};
66226031Sstas
67226031Sstas/**
68226031Sstas * Allocate an array
69226031Sstas *
70226031Sstas * @return A new allocated array, free with heim_release()
71226031Sstas */
72226031Sstas
73226031Sstasheim_array_t
74226031Sstasheim_array_create(void)
75226031Sstas{
76226031Sstas    heim_array_t array;
77226031Sstas
78226031Sstas    array = _heim_alloc_object(&array_object, sizeof(*array));
79226031Sstas    if (array == NULL)
80226031Sstas	return NULL;
81226031Sstas
82226031Sstas    array->val = NULL;
83226031Sstas    array->len = 0;
84226031Sstas
85226031Sstas    return array;
86226031Sstas}
87226031Sstas
88226031Sstas/**
89226031Sstas * Get type id of an dict
90226031Sstas *
91226031Sstas * @return the type id
92226031Sstas */
93226031Sstas
94226031Sstasheim_tid_t
95226031Sstasheim_array_get_type_id(void)
96226031Sstas{
97226031Sstas    return HEIM_TID_ARRAY;
98226031Sstas}
99226031Sstas
100226031Sstas/**
101226031Sstas * Append object to array
102226031Sstas *
103226031Sstas * @param array array to add too
104226031Sstas * @param object the object to add
105226031Sstas *
106226031Sstas * @return zero if added, errno otherwise
107226031Sstas */
108226031Sstas
109226031Sstasint
110226031Sstasheim_array_append_value(heim_array_t array, heim_object_t object)
111226031Sstas{
112226031Sstas    heim_object_t *ptr;
113226031Sstas
114226031Sstas    ptr = realloc(array->val, (array->len + 1) * sizeof(array->val[0]));
115226031Sstas    if (ptr == NULL)
116226031Sstas	return ENOMEM;
117226031Sstas    array->val = ptr;
118226031Sstas    array->val[array->len++] = heim_retain(object);
119226031Sstas
120226031Sstas    return 0;
121226031Sstas}
122226031Sstas
123226031Sstas/**
124226031Sstas * Iterate over all objects in array
125226031Sstas *
126226031Sstas * @param array array to iterate over
127226031Sstas * @param fn function to call on each object
128226031Sstas * @param ctx context passed to fn
129226031Sstas */
130226031Sstas
131226031Sstasvoid
132226031Sstasheim_array_iterate_f(heim_array_t array, heim_array_iterator_f_t fn, void *ctx)
133226031Sstas{
134226031Sstas    size_t n;
135226031Sstas    for (n = 0; n < array->len; n++)
136226031Sstas	fn(array->val[n], ctx);
137226031Sstas}
138226031Sstas
139226031Sstas#ifdef __BLOCKS__
140226031Sstas/**
141226031Sstas * Iterate over all objects in array
142226031Sstas *
143226031Sstas * @param array array to iterate over
144226031Sstas * @param fn block to call on each object
145226031Sstas */
146226031Sstas
147226031Sstasvoid
148226031Sstasheim_array_iterate(heim_array_t array, void (^fn)(heim_object_t))
149226031Sstas{
150226031Sstas    size_t n;
151226031Sstas    for (n = 0; n < array->len; n++)
152226031Sstas	fn(array->val[n]);
153226031Sstas}
154226031Sstas#endif
155226031Sstas
156226031Sstas/**
157226031Sstas * Get length of array
158226031Sstas *
159226031Sstas * @param array array to get length of
160226031Sstas *
161226031Sstas * @return length of array
162226031Sstas */
163226031Sstas
164226031Sstassize_t
165226031Sstasheim_array_get_length(heim_array_t array)
166226031Sstas{
167226031Sstas    return array->len;
168226031Sstas}
169226031Sstas
170226031Sstas/**
171226031Sstas * Copy value of array
172226031Sstas *
173226031Sstas * @param array array copy object from
174226031Sstas * @param idx index of object, 0 based, must be smaller then
175226031Sstas *        heim_array_get_length()
176226031Sstas *
177226031Sstas * @return a retained copy of the object
178226031Sstas */
179226031Sstas
180226031Sstasheim_object_t
181226031Sstasheim_array_copy_value(heim_array_t array, size_t idx)
182226031Sstas{
183226031Sstas    if (idx >= array->len)
184226031Sstas	heim_abort("index too large");
185226031Sstas    return heim_retain(array->val[idx]);
186226031Sstas}
187226031Sstas
188226031Sstas/**
189226031Sstas * Delete value at idx
190226031Sstas *
191226031Sstas * @param array the array to modify
192226031Sstas * @param idx the key to delete
193226031Sstas */
194226031Sstas
195226031Sstasvoid
196226031Sstasheim_array_delete_value(heim_array_t array, size_t idx)
197226031Sstas{
198226031Sstas    heim_object_t obj;
199226031Sstas    if (idx >= array->len)
200226031Sstas	heim_abort("index too large");
201226031Sstas    obj = array->val[idx];
202226031Sstas
203226031Sstas    array->len--;
204226031Sstas
205226031Sstas    if (idx < array->len)
206226031Sstas	memmove(&array->val[idx], &array->val[idx + 1],
207226031Sstas		(array->len - idx) * sizeof(array->val[0]));
208226031Sstas
209226031Sstas    heim_release(obj);
210226031Sstas}
211226031Sstas
212226031Sstas#ifdef __BLOCKS__
213226031Sstas/**
214226031Sstas * Get value at idx
215226031Sstas *
216226031Sstas * @param array the array to modify
217226031Sstas * @param idx the key to delete
218226031Sstas */
219226031Sstas
220226031Sstasvoid
221226128Sstasheim_array_filter(heim_array_t array, int (^block)(heim_object_t))
222226031Sstas{
223226031Sstas    size_t n = 0;
224226031Sstas
225226031Sstas    while (n < array->len) {
226226031Sstas	if (block(array->val[n])) {
227226031Sstas	    heim_array_delete_value(array, n);
228226031Sstas	} else {
229226031Sstas	    n++;
230226031Sstas	}
231226031Sstas    }
232226031Sstas}
233226031Sstas
234226031Sstas#endif /* __BLOCKS__ */
235