ccn_indexbuf.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_indexbuf.c
00003  * @brief Support for expandable buffer of non-negative values.
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 #include <stddef.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <ccn/indexbuf.h>
00024 
00025 #define ELEMENT size_t
00026 
00027 /**
00028  * Create a new indexbuf.
00029  */
00030 struct ccn_indexbuf *
00031 ccn_indexbuf_create(void)
00032 {
00033     struct ccn_indexbuf *c;
00034     c = calloc(1, sizeof(*c));
00035     return(c);
00036 }
00037 
00038 /**
00039  * Deallocate indexbuf.
00040  */
00041 void
00042 ccn_indexbuf_destroy(struct ccn_indexbuf **cbp)
00043 {
00044     struct ccn_indexbuf *c = *cbp;
00045     if (c != NULL) {
00046         if (c->buf != NULL) {
00047             free(c->buf);
00048         }
00049         free(c);
00050         *cbp = NULL;
00051     }
00052 }
00053 
00054 /**
00055  * Expand buffer as necessary to hold at least n more values.
00056  * @returns pointer to reserved space
00057  */
00058 ELEMENT *
00059 ccn_indexbuf_reserve(struct ccn_indexbuf *c, size_t n)
00060 {
00061     size_t newlim = n + c->n;
00062     size_t oldlim = c->limit;
00063     ELEMENT *buf = c->buf;
00064     if (newlim < n)
00065         return(NULL);
00066     if (newlim > oldlim) {
00067         if (2 * oldlim > newlim)
00068             newlim = 2 * oldlim;
00069 #ifdef CCN_NOREALLOC
00070         buf = malloc(newlim * sizeof(ELEMENT));
00071         if (buf == NULL)
00072             return(NULL);
00073         memcpy(buf, c->buf, oldlim * sizeof(ELEMENT));
00074         free(c->buf);
00075 #else
00076         buf = realloc(c->buf, newlim * sizeof(ELEMENT));
00077         if (buf == NULL)
00078             return(NULL);
00079 #endif
00080         memset(buf + oldlim, 0, (newlim - oldlim) * sizeof(ELEMENT));
00081         c->buf = buf;
00082         c->limit = newlim;
00083     }
00084     buf += c->n;
00085     return(buf);
00086 }
00087 
00088 /**
00089  * Append multiple elements to the indexbuf.
00090  * @returns 0 for success, -1 for failure.
00091  */
00092 int
00093 ccn_indexbuf_append(struct ccn_indexbuf *c, const ELEMENT *p, size_t n)
00094 {
00095     ELEMENT *dst = ccn_indexbuf_reserve(c, n);
00096     if (dst == NULL)
00097         return(-1);
00098     memcpy(dst, p, n * sizeof(ELEMENT));
00099     c->n += n;
00100     return(0);
00101 }
00102 
00103 /**
00104  * Append v to the indexbuf
00105  * @returns 0 for success, -1 for failure.
00106  */
00107 int
00108 ccn_indexbuf_append_element(struct ccn_indexbuf *c, ELEMENT v)
00109 {
00110     ELEMENT *dst = ccn_indexbuf_reserve(c, 1);
00111     if (dst == NULL)
00112         return(-1);
00113     *dst = v;
00114     c->n += 1;
00115     return(0);
00116 }
00117 
00118 /**
00119  * @returns index at which the element was found or appended, or -1 if not found.
00120  */
00121 int
00122 ccn_indexbuf_member(struct ccn_indexbuf *x, ELEMENT val)
00123 {
00124     int i;
00125     if (x == NULL)
00126         return (-1);
00127     for (i = x->n - 1; i >= 0; i--)
00128         if (x->buf[i] == val)
00129             return(i);
00130     return(-1);
00131 }
00132 
00133 /**
00134  * Removes up to one instance of val from the indexbuf.
00135  * Order of elements not preserved.
00136  */
00137 void
00138 ccn_indexbuf_remove_element(struct ccn_indexbuf *x, ELEMENT val)
00139 {
00140     int i;
00141     if (x == NULL) return;
00142     for (i = x->n - 1; i >= 0; i--)
00143         if (x->buf[i] == val) {
00144             x->buf[i] = x->buf[--x->n]; /* move last element into vacant spot */
00145             return;
00146         }
00147 }
00148 
00149 /**
00150  * @returns index at which the element was found or appended,
00151  *          or -1 in case of error.
00152  */
00153 int
00154 ccn_indexbuf_set_insert(struct ccn_indexbuf *x, ELEMENT val)
00155 {
00156     int i;
00157     if (x == NULL)
00158         return (-1);
00159     for (i = 0; i < x->n; i++)
00160         if (x->buf[i] == val)
00161             return(i);
00162     if (ccn_indexbuf_append_element(x, val) < 0)
00163         return(-1);
00164     return(i);
00165 }
00166 
00167 /**
00168  * Removes first occurrence of val, preserving order
00169  * @returns index at which the element was found,
00170  *          or -1 if the element was not found.
00171  */
00172 int
00173 ccn_indexbuf_remove_first_match(struct ccn_indexbuf *x, ELEMENT val)
00174 {
00175     int i;
00176     int n;
00177     if (x == NULL)
00178         return (-1);
00179     for (i = 0, n = x->n; i < n; i++) {
00180         if (x->buf[i] == val) {
00181             if (i + 1 < n)
00182                 memmove(&(x->buf[i]),
00183                         &(x->buf[i + 1]),
00184                         sizeof(x->buf[i]) * (n - i - 1));
00185             x->n--;
00186             return(i);
00187         }
00188     }
00189     return(-1);
00190 }
00191 
00192 /**
00193  * If val is present in the indexbuf, move it to the final place.
00194  */
00195 void
00196 ccn_indexbuf_move_to_end(struct ccn_indexbuf *x, ELEMENT val)
00197 {
00198     int i;
00199     int n;
00200     if (x == NULL)
00201         return;
00202     for (i = 0, n = x->n; i + 1 < n; i++) {
00203         if (x->buf[i] == val) {
00204             memmove(&(x->buf[i]),
00205                     &(x->buf[i + 1]),
00206                     sizeof(x->buf[i]) * (n - i - 1));
00207             x->buf[n - 1] = val;
00208             return;
00209         }
00210     }
00211 }
00212 
00213 /**
00214  * If val is present in the indexbuf, move it to the first place.
00215  */
00216 void
00217 ccn_indexbuf_move_to_front(struct ccn_indexbuf *x, ELEMENT val)
00218 {
00219     int i;
00220     int n;
00221     if (x == NULL)
00222         return;
00223     for (i = 0, n = x->n; i < n; i++) {
00224         if (x->buf[i] == val) {
00225             memmove(&(x->buf[1]),
00226                     &(x->buf[0]),
00227                     sizeof(x->buf[i]) * i);
00228             x->buf[0] = val;
00229             return;
00230         }
00231     }
00232 
00233 }
00234 

Generated on Thu Feb 16 00:44:00 2012 for Content-Centric Networking in C by  doxygen 1.5.6