Back to index

lightning-sunbird  0.9+nobinonly
cairo-array.c
Go to the documentation of this file.
00001 /* cairo - a vector graphics library with display and print output
00002  *
00003  * Copyright © 2004 Red Hat, Inc
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it either under the terms of the GNU Lesser General Public
00007  * License version 2.1 as published by the Free Software Foundation
00008  * (the "LGPL") or, at your option, under the terms of the Mozilla
00009  * Public License Version 1.1 (the "MPL"). If you do not alter this
00010  * notice, a recipient may use your version of this file under either
00011  * the MPL or the LGPL.
00012  *
00013  * You should have received a copy of the LGPL along with this library
00014  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00016  * You should have received a copy of the MPL along with this library
00017  * in the file COPYING-MPL-1.1
00018  *
00019  * The contents of this file are subject to the Mozilla Public License
00020  * Version 1.1 (the "License"); you may not use this file except in
00021  * compliance with the License. You may obtain a copy of the License at
00022  * http://www.mozilla.org/MPL/
00023  *
00024  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
00025  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
00026  * the specific language governing rights and limitations.
00027  *
00028  * The Original Code is the cairo graphics library.
00029  *
00030  * The Initial Developer of the Original Code is University of Southern
00031  * California.
00032  *
00033  * Contributor(s):
00034  *     Kristian Høgsberg <krh@redhat.com>
00035  */
00036 
00037 #include "cairoint.h"
00038 
00039 void
00040 _cairo_array_init (cairo_array_t *array, int element_size)
00041 {
00042     array->size = 0;
00043     array->num_elements = 0;
00044     array->element_size = element_size;
00045     array->elements = NULL;
00046 }
00047 
00048 void
00049 _cairo_array_fini (cairo_array_t *array)
00050 {
00051     free (array->elements);
00052 }
00053 
00054 cairo_status_t
00055 _cairo_array_grow_by (cairo_array_t *array, int additional)
00056 {
00057     char *new_elements;
00058     int old_size = array->size;
00059     int required_size = array->num_elements + additional;
00060     int new_size;
00061 
00062     if (required_size <= old_size)
00063        return CAIRO_STATUS_SUCCESS;
00064 
00065     if (old_size == 0)
00066        new_size = 1;
00067     else
00068        new_size = old_size * 2;
00069 
00070     while (new_size < required_size)
00071        new_size = new_size * 2;
00072 
00073     array->size = new_size;
00074     new_elements = realloc (array->elements,
00075                          array->size * array->element_size);
00076 
00077     if (new_elements == NULL) {
00078        array->size = old_size;
00079        return CAIRO_STATUS_NO_MEMORY;
00080     }
00081 
00082     array->elements = new_elements;
00083 
00084     return CAIRO_STATUS_SUCCESS;
00085 }
00086 
00087 void
00088 _cairo_array_truncate (cairo_array_t *array, int num_elements)
00089 {
00090     if (num_elements < array->num_elements)
00091        array->num_elements = num_elements;
00092 }
00093 
00094 void *
00095 _cairo_array_index (cairo_array_t *array, int index)
00096 {
00097     assert (0 <= index && index < array->num_elements);
00098 
00099     return (void *) &array->elements[index * array->element_size];
00100 }
00101 
00102 void
00103 _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
00104 {
00105     memcpy (dst, _cairo_array_index (array, index), array->element_size);
00106 }
00107 
00108 void *
00109 _cairo_array_append (cairo_array_t *array,
00110                    const void *elements, int num_elements)
00111 {
00112     cairo_status_t status;
00113     void *dest;
00114 
00115     status = _cairo_array_grow_by (array, num_elements);
00116     if (status != CAIRO_STATUS_SUCCESS)
00117        return NULL;
00118 
00119     assert (array->num_elements + num_elements <= array->size);
00120 
00121     dest = &array->elements[array->num_elements * array->element_size];
00122     array->num_elements += num_elements;
00123 
00124     if (elements != NULL)
00125        memcpy (dest, elements, num_elements * array->element_size);
00126 
00127     return dest;
00128 }
00129 
00130 int
00131 _cairo_array_num_elements (cairo_array_t *array)
00132 {
00133     return array->num_elements;
00134 }
00135 
00136 /* cairo_user_data_array_t */
00137 
00138 typedef struct {
00139     const cairo_user_data_key_t *key;
00140     void *user_data;
00141     cairo_destroy_func_t destroy;
00142 } cairo_user_data_slot_t;
00143 
00153 void
00154 _cairo_user_data_array_init (cairo_user_data_array_t *array)
00155 {
00156     _cairo_array_init (array, sizeof (cairo_user_data_slot_t));
00157 }
00158 
00166 void
00167 _cairo_user_data_array_fini (cairo_user_data_array_t *array)
00168 {
00169     int i, num_slots;
00170     cairo_user_data_slot_t *slots;
00171 
00172     num_slots = array->num_elements;
00173     slots = (cairo_user_data_slot_t *) array->elements;
00174     for (i = 0; i < num_slots; i++) {
00175        if (slots[i].user_data != NULL && slots[i].destroy != NULL)
00176            slots[i].destroy (slots[i].user_data);
00177     }
00178 
00179     _cairo_array_fini (array);
00180 }
00181 
00194 void *
00195 _cairo_user_data_array_get_data (cairo_user_data_array_t     *array,
00196                              const cairo_user_data_key_t *key)
00197 {
00198     int i, num_slots;
00199     cairo_user_data_slot_t *slots;
00200 
00201     /* We allow this to support degenerate objects such as
00202      * cairo_image_surface_nil. */
00203     if (array == NULL)
00204        return NULL;
00205 
00206     num_slots = array->num_elements;
00207     slots = (cairo_user_data_slot_t *) array->elements;
00208     for (i = 0; i < num_slots; i++) {
00209        if (slots[i].key == key)
00210            return slots[i].user_data;
00211     }
00212 
00213     return NULL;
00214 }
00215 
00232 cairo_status_t
00233 _cairo_user_data_array_set_data (cairo_user_data_array_t     *array,
00234                              const cairo_user_data_key_t *key,
00235                              void                     *user_data,
00236                              cairo_destroy_func_t             destroy)
00237 {
00238     int i, num_slots;
00239     cairo_user_data_slot_t *slots, *s;
00240 
00241     s = NULL;
00242     num_slots = array->num_elements;
00243     slots = (cairo_user_data_slot_t *) array->elements;
00244     for (i = 0; i < num_slots; i++) {
00245        if (slots[i].key == key) {
00246            if (slots[i].user_data != NULL && slots[i].destroy != NULL)
00247               slots[i].destroy (slots[i].user_data);
00248            s = &slots[i];
00249            break;
00250        }
00251        if (user_data && slots[i].user_data == NULL) {
00252            s = &slots[i];   /* Have to keep searching for an exact match */
00253        }
00254     }
00255 
00256     if (user_data == NULL) {
00257        if (s != NULL) {
00258            s->key = NULL;
00259            s->user_data = NULL;
00260            s->destroy = NULL;
00261        }
00262 
00263        return CAIRO_STATUS_SUCCESS;
00264        
00265     } else {
00266        if (s == NULL)
00267            s = _cairo_array_append (array, NULL, 1);
00268        if (s == NULL)
00269            return CAIRO_STATUS_NO_MEMORY;
00270 
00271        s->key = key;
00272        s->user_data = user_data;
00273        s->destroy = destroy;
00274     }
00275 
00276     return CAIRO_STATUS_SUCCESS;
00277 }
00278