source: roaraudio/libroar/kstore.c @ 6077:defd0f59ac8b

Last change on this file since 6077:defd0f59ac8b was 6077:defd0f59ac8b, checked in by phi, 9 years ago

do not work on items not filled

File size: 6.0 KB
Line 
1//kstore.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2015
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define _LEN_DEFAULT 16
39
40struct binkv {
41 char * key;
42 void * value;
43};
44
45struct roar_kstore {
46 size_t refc;
47 int (*ref)(void *);
48 int (*unref)(void *);
49 const char * (*get_key)(void *);
50 size_t len;
51 struct binkv * kv;
52};
53
54struct roar_kstore * roar_kstore_new(ssize_t len,
55                                     int (*ref)(void *), int (*unref)(void *),
56                                     const char * (*get_key)(void *)) {
57 struct roar_kstore * ret = roar_mm_malloc(sizeof(struct roar_kstore));
58 int err;
59
60 if ( ret == NULL )
61  return NULL;
62
63 memset(ret, 0, sizeof(struct roar_kstore));
64
65 if ( len == -1 )
66  len = _LEN_DEFAULT;
67
68 ret->kv = roar_mm_malloc(len*sizeof(struct binkv));
69 if ( ret->kv == NULL ) {
70  err = roar_error;
71  roar_mm_free(ret);
72  roar_error = err;
73  return NULL;
74 }
75
76 memset(ret->kv, 0, len*sizeof(struct binkv));
77
78 ret->refc    = 1;
79 ret->ref     = ref;
80 ret->unref   = unref;
81 ret->get_key = get_key;
82 ret->len     = len;
83
84 return ret;
85}
86
87int                  roar_kstore_ref(struct roar_kstore * store) {
88 if ( store == NULL ) {
89  roar_err_set(ROAR_ERROR_FAULT);
90  return -1;
91 }
92
93 store->refc++;
94
95 return 0;
96}
97
98int                  roar_kstore_unref(struct roar_kstore * store) {
99 size_t i;
100
101 if ( store == NULL ) {
102  roar_err_set(ROAR_ERROR_FAULT);
103  return -1;
104 }
105
106 store->refc--;
107
108 if ( store->refc )
109  return 0;
110
111 if ( store->unref != NULL ) {
112  for (i = 0; i < store->len; i++) {
113   if ( store->kv[i].key == NULL )
114    continue;
115
116   if ( store->unref(store->kv[i].value) == -1 )
117    return -1;
118   roar_mm_free(store->kv[i].key);
119   store->kv[i].key = NULL;
120   store->kv[i].value = NULL;
121  }
122 }
123
124 roar_mm_free(store->kv);
125 roar_mm_free(store);
126
127 return 0;
128}
129
130int                  roar_kstore_add(struct roar_kstore * store, void * obj, const char * key) {
131 size_t i;
132 int err;
133
134 if ( store == NULL ) {
135  roar_err_set(ROAR_ERROR_FAULT);
136  return -1;
137 }
138
139 if ( key == NULL && store->get_key != NULL )
140  key = store->get_key(obj);
141
142 if ( key == NULL ) {
143  roar_err_set(ROAR_ERROR_INVAL);
144  return -1;
145 }
146
147 for (i = 0; i < store->len; i++) {
148  if ( store->kv[i].key == NULL )
149   continue;
150  if ( !strcmp(store->kv[i].key, key) ) {
151   roar_err_set(ROAR_ERROR_EXIST);
152   return -1;
153  }
154 }
155
156 for (i = 0; i < store->len; i++) {
157  if ( store->kv[i].key != NULL )
158   continue;
159
160  store->kv[i].key = roar_mm_strdup(key);
161
162  if ( store->kv[i].key == NULL )
163   return -1;
164
165  store->kv[i].value = obj;
166
167  if ( store->ref != NULL ) {
168   if ( store->ref(obj) == -1 ) {
169    err = roar_error;
170    roar_mm_free(store->kv[i].key);
171    store->kv[i].key = NULL;
172    roar_error = err;
173    return -1;
174   }
175  }
176  return 0;
177 }
178
179 roar_err_set(ROAR_ERROR_NOSPC);
180 return -1;
181}
182
183void *               roar_kstore_get(struct roar_kstore * store, const char * key) {
184 size_t i;
185
186 if ( store == NULL ) {
187  roar_err_set(ROAR_ERROR_FAULT);
188  return NULL;
189 }
190
191 for (i = 0; i < store->len; i++) {
192  if ( store->kv[i].key != NULL && !strcmp(store->kv[i].key, key) ) {
193   if ( store->ref != NULL )
194    if ( store->ref(store->kv[i].value) == -1 )
195     return NULL;
196   return store->kv[i].value;
197  }
198 }
199
200 roar_err_set(ROAR_ERROR_NOENT);
201 return NULL;
202}
203
204int                  roar_kstore_delete(struct roar_kstore * store, const char * key) {
205 size_t i;
206
207 if ( store == NULL ) {
208  roar_err_set(ROAR_ERROR_FAULT);
209  return -1;
210 }
211
212 for (i = 0; i < store->len; i++) {
213  if ( store->kv[i].key != NULL && !strcmp(store->kv[i].key, key) ) {
214   if ( store->unref != NULL )
215    if ( store->unref(store->kv[i].value) == -1 )
216     return -1;
217   roar_mm_free(store->kv[i].key);
218   store->kv[i].key = NULL;
219   store->kv[i].value = NULL;
220   return 0;
221  }
222 }
223
224 roar_err_set(ROAR_ERROR_NOENT);
225 return -1;
226}
227
228const char *         roar_kstore_name(struct roar_kstore * store, const void * obj) {
229 size_t i;
230
231 if ( store == NULL ) {
232  roar_err_set(ROAR_ERROR_FAULT);
233  return NULL;
234 }
235
236 for (i = 0; i < store->len; i++) {
237  ROAR_DBG("roar_kstore_name(store=%p, obj=%p): store->kv[%i].key=%p'%s', store->kv[%i].value=%p", store, obj, (int)i, store->kv[i].key, store->kv[i].key, (int)i, store->kv[i].value);
238  if ( store->kv[i].key != NULL && store->kv[i].value == obj )
239   return store->kv[i].key;
240 }
241
242 roar_err_set(ROAR_ERROR_NOENT);
243 return NULL;
244}
245
246int                  roar_kstore_foreach(struct roar_kstore * store, int (*func)(void *obj, void *userdata), void * userdata) {
247 size_t i;
248
249 if ( store == NULL || func == NULL ) {
250  roar_err_set(ROAR_ERROR_FAULT);
251  return -1;
252 }
253
254 for (i = 0; i < store->len; i++) {
255  if ( store->kv[i].key == NULL )
256   continue;
257  if ( store->ref != NULL )
258   store->ref(store->kv[i].value);
259  func(store->kv[i].value, userdata);
260  if ( store->unref != NULL )
261   store->unref(store->kv[i].value);
262 }
263
264 return 0;
265}
266
267//ll
Note: See TracBrowser for help on using the repository browser.