/ base / array.c
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__ */