array.c
1 /* 2 * Copyright (c) 2010 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "baselocl.h" 37 38 /* 39 * 40 */ 41 42 struct heim_array_data { 43 size_t len; 44 heim_object_t *val; 45 }; 46 47 static void 48 array_dealloc(heim_object_t ptr) 49 { 50 heim_array_t array = ptr; 51 size_t n; 52 for (n = 0; n < array->len; n++) 53 heim_release(array->val[n]); 54 free(array->val); 55 } 56 57 static struct heim_type_data array_object = { 58 HEIM_TID_ARRAY, 59 "dict-object", 60 NULL, 61 array_dealloc, 62 NULL, 63 NULL, 64 NULL 65 }; 66 67 /** 68 * Allocate an array 69 * 70 * @return A new allocated array, free with heim_release() 71 */ 72 73 heim_array_t 74 heim_array_create(void) 75 { 76 heim_array_t array; 77 78 array = _heim_alloc_object(&array_object, sizeof(*array)); 79 if (array == NULL) 80 return NULL; 81 82 array->val = NULL; 83 array->len = 0; 84 85 return array; 86 } 87 88 /** 89 * Get type id of an dict 90 * 91 * @return the type id 92 */ 93 94 heim_tid_t 95 heim_array_get_type_id(void) 96 { 97 return HEIM_TID_ARRAY; 98 } 99 100 /** 101 * Append object to array 102 * 103 * @param array array to add too 104 * @param object the object to add 105 * 106 * @return zero if added, errno otherwise 107 */ 108 109 int 110 heim_array_append_value(heim_array_t array, heim_object_t object) 111 { 112 heim_object_t *ptr; 113 114 ptr = realloc(array->val, (array->len + 1) * sizeof(array->val[0])); 115 if (ptr == NULL) 116 return ENOMEM; 117 array->val = ptr; 118 array->val[array->len++] = heim_retain(object); 119 120 return 0; 121 } 122 123 /** 124 * Iterate over all objects in array 125 * 126 * @param array array to iterate over 127 * @param fn function to call on each object 128 * @param ctx context passed to fn 129 */ 130 131 void 132 heim_array_iterate_f(heim_array_t array, 133 void *ctx, 134 heim_array_iterator_f_t fn) 135 { 136 int stop = 0; 137 size_t n; 138 139 for (n = 0; n < array->len && !stop; n++) 140 fn(array->val[n], &stop, ctx); 141 } 142 143 #ifdef __BLOCKS__ 144 /** 145 * Iterate over all objects in array 146 * 147 * @param array array to iterate over 148 * @param fn block to call on each object 149 */ 150 151 void 152 heim_array_iterate(heim_array_t array, heim_array_iterator_t fn) 153 { 154 int stop = 0; 155 size_t n; 156 157 for (n = 0; n < array->len && !stop; n++) 158 fn(array->val[n], &stop); 159 } 160 #endif 161 162 /** 163 * Get length of array 164 * 165 * @param array array to get length of 166 * 167 * @return length of array 168 */ 169 170 size_t 171 heim_array_get_length(heim_array_t array) 172 { 173 return array->len; 174 } 175 176 /** 177 * Copy value of array 178 * 179 * @param array array copy object from 180 * @param idx index of object, 0 based, must be smaller then 181 * heim_array_get_length() 182 * 183 * @return a retained copy of the object 184 */ 185 186 heim_object_t 187 heim_array_copy_value(heim_array_t array, size_t idx) 188 { 189 if (idx >= array->len) 190 heim_abort("index too large"); 191 return heim_retain(array->val[idx]); 192 } 193 194 /** 195 * Delete value at idx 196 * 197 * @param array the array to modify 198 * @param idx the key to delete 199 */ 200 201 void 202 heim_array_delete_value(heim_array_t array, size_t idx) 203 { 204 heim_object_t obj; 205 if (idx >= array->len) 206 heim_abort("index too large"); 207 obj = array->val[idx]; 208 209 array->len--; 210 211 if (idx < array->len) 212 memmove(&array->val[idx], &array->val[idx + 1], 213 (array->len - idx) * sizeof(array->val[0])); 214 215 heim_release(obj); 216 } 217 218 #ifdef __BLOCKS__ 219 /** 220 * Get value at idx 221 * 222 * @param array the array to modify 223 * @param idx the key to delete 224 */ 225 226 void 227 heim_array_filter(heim_array_t array, int (^block)(heim_object_t)) 228 { 229 size_t n = 0; 230 231 while (n < array->len) { 232 if (block(array->val[n])) { 233 heim_array_delete_value(array, n); 234 } else { 235 n++; 236 } 237 } 238 } 239 240 #endif /* __BLOCKS__ */