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         buf = realloc(c->buf, newlim * sizeof(ELEMENT));
00070         if (buf == NULL)
00071             return(NULL);
00072         memset(buf + oldlim, 0, (newlim - oldlim) * sizeof(ELEMENT));
00073         c->buf = buf;
00074         c->limit = newlim;
00075     }
00076     buf += c->n;
00077     return(buf);
00078 }
00079 
00080 /**
00081  * Append multiple elements to the indexbuf.
00082  * @returns 0 for success, -1 for failure.
00083  */
00084 int
00085 ccn_indexbuf_append(struct ccn_indexbuf *c, const ELEMENT *p, size_t n)
00086 {
00087     ELEMENT *dst = ccn_indexbuf_reserve(c, n);
00088     if (dst == NULL)
00089         return(-1);
00090     memcpy(dst, p, n * sizeof(ELEMENT));
00091     c->n += n;
00092     return(0);
00093 }
00094 
00095 /**
00096  * Append v to the indexbuf
00097  * @returns 0 for success, -1 for failure.
00098  */
00099 int
00100 ccn_indexbuf_append_element(struct ccn_indexbuf *c, ELEMENT v)
00101 {
00102     ELEMENT *dst = ccn_indexbuf_reserve(c, 1);
00103     if (dst == NULL)
00104         return(-1);
00105     *dst = v;
00106     c->n += 1;
00107     return(0);
00108 }
00109 
00110 /**
00111  * @returns index at which the element was found or appended, or -1 if not found.
00112  */
00113 int
00114 ccn_indexbuf_member(struct ccn_indexbuf *x, ELEMENT val)
00115 {
00116     int i;
00117     if (x == NULL)
00118         return (-1);
00119     for (i = x->n - 1; i >= 0; i--)
00120         if (x->buf[i] == val)
00121             return(i);
00122     return(-1);
00123 }
00124 
00125 /**
00126  * Removes up to one instance of val from the indexbuf.
00127  * Order of elements not preserved.
00128  */
00129 void
00130 ccn_indexbuf_remove_element(struct ccn_indexbuf *x, ELEMENT val)
00131 {
00132     int i;
00133     if (x == NULL) return;
00134     for (i = x->n - 1; i >= 0; i--)
00135         if (x->buf[i] == val) {
00136             x->buf[i] = x->buf[--x->n]; /* move last element into vacant spot */
00137             return;
00138         }
00139 }
00140 
00141 /**
00142  * @returns index at which the element was found or appended,
00143  *          or -1 in case of error.
00144  */
00145 int
00146 ccn_indexbuf_set_insert(struct ccn_indexbuf *x, ELEMENT val)
00147 {
00148     int i;
00149     if (x == NULL)
00150         return (-1);
00151     for (i = 0; i < x->n; i++)
00152         if (x->buf[i] == val)
00153             return(i);
00154     if (ccn_indexbuf_append_element(x, val) < 0)
00155         return(-1);
00156     return(i);
00157 }
00158 
00159 /**
00160  * Removes first occurrence of val, preserving order
00161  * @returns index at which the element was found,
00162  *          or -1 if the element was not found.
00163  */
00164 int
00165 ccn_indexbuf_remove_first_match(struct ccn_indexbuf *x, ELEMENT val)
00166 {
00167     int i;
00168     int n;
00169     if (x == NULL)
00170         return (-1);
00171     for (i = 0, n = x->n; i < n; i++) {
00172         if (x->buf[i] == val) {
00173             if (i + 1 < n)
00174                 memmove(&(x->buf[i]),
00175                         &(x->buf[i + 1]),
00176                         sizeof(x->buf[i]) * (n - i - 1));
00177             x->n--;
00178             return(i);
00179         }
00180     }
00181     return(-1);
00182 }
00183 
00184 /**
00185  * If val is present in the indexbuf, move it to the final place.
00186  */
00187 void
00188 ccn_indexbuf_move_to_end(struct ccn_indexbuf *x, ELEMENT val)
00189 {
00190     int i;
00191     int n;
00192     if (x == NULL)
00193         return;
00194     for (i = 0, n = x->n; i + 1 < n; i++) {
00195         if (x->buf[i] == val) {
00196             memmove(&(x->buf[i]),
00197                     &(x->buf[i + 1]),
00198                     sizeof(x->buf[i]) * (n - i - 1));
00199             x->buf[n - 1] = val;
00200             return;
00201         }
00202     }
00203 }
00204 
00205 /**
00206  * If val is present in the indexbuf, move it to the first place.
00207  */
00208 void
00209 ccn_indexbuf_move_to_front(struct ccn_indexbuf *x, ELEMENT val)
00210 {
00211     int i;
00212     int n;
00213     if (x == NULL)
00214         return;
00215     for (i = 0, n = x->n; i < n; i++) {
00216         if (x->buf[i] == val) {
00217             memmove(&(x->buf[1]),
00218                     &(x->buf[0]),
00219                     sizeof(x->buf[i]) * i);
00220             x->buf[0] = val;
00221             return;
00222         }
00223     }
00224 
00225 }
00226 
Generated on Fri May 13 16:27:02 2011 for Content-Centric Networking in C by  doxygen 1.6.3