blob: 3d04e13f2bfa172dbf0bb684800020eca8678792 [file] [log] [blame]
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -07001/*
2 * ccn_indexbuf.cc
3 * Abstraction
4 *
5 * Created by Ilya on 7/29/11.
6 * Copyright 2011 __MyCompanyName__. All rights reserved.
7 *
8 */
9
10#include "ccn_indexbuf.h"
11
12/**
13 * @file ccn_indexbuf.c
14 * @brief Support for expandable buffer of non-negative values.
15 *
16 * Part of the CCNx C Library.
17 *
18 * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
19 *
20 * This library is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU Lesser General Public License version 2.1
22 * as published by the Free Software Foundation.
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details. You should have received
27 * a copy of the GNU Lesser General Public License along with this library;
28 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
29 * Fifth Floor, Boston, MA 02110-1301 USA.
30 */
31#include <stddef.h>
32#include <stdlib.h>
33#include <string.h>
34
35#define ELEMENT size_t
36
37/**
38 * Create a new indexbuf.
39 */
40struct ccn_indexbuf *
41ccn_indexbuf_create(void)
42{
43 struct ccn_indexbuf *c;
44 c = (ccn_indexbuf*)calloc(1, sizeof(*c));
45 return(c);
46}
47
48/**
49 * Deallocate indexbuf.
50 */
51void
52ccn_indexbuf_destroy(struct ccn_indexbuf **cbp)
53{
54 struct ccn_indexbuf *c = *cbp;
55 if (c != NULL) {
56 if (c->buf != NULL) {
57 free(c->buf);
58 }
59 free(c);
60 *cbp = NULL;
61 }
62}
63
64/**
65 * Expand buffer as necessary to hold at least n more values.
66 * @returns pointer to reserved space
67 */
68ELEMENT *
69ccn_indexbuf_reserve(struct ccn_indexbuf *c, size_t n)
70{
71 size_t newlim = n + c->n;
72 size_t oldlim = c->limit;
73 ELEMENT *buf = c->buf;
74 if (newlim < n)
75 return(NULL);
76 if (newlim > oldlim) {
77 if (2 * oldlim > newlim)
78 newlim = 2 * oldlim;
79 buf = (size_t*)realloc(c->buf, newlim * sizeof(ELEMENT));
80 if (buf == NULL)
81 return(NULL);
82 memset(buf + oldlim, 0, (newlim - oldlim) * sizeof(ELEMENT));
83 c->buf = buf;
84 c->limit = newlim;
85 }
86 buf += c->n;
87 return(buf);
88}
89
90/**
91 * Append multiple elements to the indexbuf.
92 * @returns 0 for success, -1 for failure.
93 */
94int
95ccn_indexbuf_append(struct ccn_indexbuf *c, const ELEMENT *p, size_t n)
96{
97 ELEMENT *dst = ccn_indexbuf_reserve(c, n);
98 if (dst == NULL)
99 return(-1);
100 memcpy(dst, p, n * sizeof(ELEMENT));
101 c->n += n;
102 return(0);
103}
104
105/**
106 * Append v to the indexbuf
107 * @returns 0 for success, -1 for failure.
108 */
109int
110ccn_indexbuf_append_element(struct ccn_indexbuf *c, ELEMENT v)
111{
112 ELEMENT *dst = ccn_indexbuf_reserve(c, 1);
113 if (dst == NULL)
114 return(-1);
115 *dst = v;
116 c->n += 1;
117 return(0);
118}
119
120/**
121 * @returns index at which the element was found or appended, or -1 if not found.
122 */
123int
124ccn_indexbuf_member(struct ccn_indexbuf *x, ELEMENT val)
125{
126 int i;
127 if (x == NULL)
128 return (-1);
129 for (i = x->n - 1; i >= 0; i--)
130 if (x->buf[i] == val)
131 return(i);
132 return(-1);
133}
134
135/**
136 * Removes up to one instance of val from the indexbuf.
137 * Order of elements not preserved.
138 */
139void
140ccn_indexbuf_remove_element(struct ccn_indexbuf *x, ELEMENT val)
141{
142 int i;
143 if (x == NULL) return;
144 for (i = x->n - 1; i >= 0; i--)
145 if (x->buf[i] == val) {
146 x->buf[i] = x->buf[--x->n]; /* move last element into vacant spot */
147 return;
148 }
149}
150
151/**
152 * @returns index at which the element was found or appended,
153 * or -1 in case of error.
154 */
155int
156ccn_indexbuf_set_insert(struct ccn_indexbuf *x, ELEMENT val)
157{
158 int i;
159 if (x == NULL)
160 return (-1);
161 for (i = 0; i < (int)x->n; i++)
162 if (x->buf[i] == val)
163 return(i);
164 if (ccn_indexbuf_append_element(x, val) < 0)
165 return(-1);
166 return(i);
167}
168
169/**
170 * Removes first occurrence of val, preserving order
171 * @returns index at which the element was found,
172 * or -1 if the element was not found.
173 */
174int
175ccn_indexbuf_remove_first_match(struct ccn_indexbuf *x, ELEMENT val)
176{
177 int i;
178 int n;
179 if (x == NULL)
180 return (-1);
181 for (i = 0, n = x->n; i < n; i++) {
182 if (x->buf[i] == val) {
183 if (i + 1 < n)
184 memmove(&(x->buf[i]),
185 &(x->buf[i + 1]),
186 sizeof(x->buf[i]) * (n - i - 1));
187 x->n--;
188 return(i);
189 }
190 }
191 return(-1);
192}
193
194/**
195 * If val is present in the indexbuf, move it to the final place.
196 */
197void
198ccn_indexbuf_move_to_end(struct ccn_indexbuf *x, ELEMENT val)
199{
200 int i;
201 int n;
202 if (x == NULL)
203 return;
204 for (i = 0, n = x->n; i + 1 < n; i++) {
205 if (x->buf[i] == val) {
206 memmove(&(x->buf[i]),
207 &(x->buf[i + 1]),
208 sizeof(x->buf[i]) * (n - i - 1));
209 x->buf[n - 1] = val;
210 return;
211 }
212 }
213}
214
215/**
216 * If val is present in the indexbuf, move it to the first place.
217 */
218void
219ccn_indexbuf_move_to_front(struct ccn_indexbuf *x, ELEMENT val)
220{
221 int i;
222 int n;
223 if (x == NULL)
224 return;
225 for (i = 0, n = x->n; i < n; i++) {
226 if (x->buf[i] == val) {
227 memmove(&(x->buf[1]),
228 &(x->buf[0]),
229 sizeof(x->buf[i]) * i);
230 x->buf[0] = val;
231 return;
232 }
233 }
234
235}
236