00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include "ks_config.h"
00031 #include "ks_assoc.h"
00032 #include "ks_string.h"
00033
00034 #ifdef HAVE_STRING_H
00035 #include <string.h>
00036 #endif
00037
00038 #ifdef HAVE_STDIO_H
00039 #include <stdio.h>
00040 #endif
00041
00042 static ks_type_t * ks_bucket_type(void);
00043
00052 static void
00053 ks_bucket_free(ks_bucket_t *b)
00054 {
00055 ks_free(b->key);
00056 ks_destroy(b->data);
00057 ks_free(b);
00058 }
00059
00070 static void
00071 ks_bucket_bappend(ks_string_t *r, ks_base_t *b)
00072 {
00073 ks_bucket_t *u = KS_CAST(ks_bucket, b);
00074 char buf[32];
00075
00076 snprintf(buf, 31, "%d", u->klen);
00077 buf[31] = '\0';
00078 ks_string_append(r, buf, strlen(buf));
00079 ks_string_append(r, ":", 1);
00080 ks_string_append(r, u->key, u->klen);
00081 ks_bappend(r, u->data);
00082 }
00083
00094 static int
00095 ks_bucket_keycompare(const ks_base_t *a, const ks_base_t *b)
00096 {
00097 #if 0
00098 const ks_bucket_t *aa = KS_CAST(ks_bucket, a);
00099 const ks_bucket_t *bb = KS_CAST(ks_bucket, b);
00100 #else
00101 const ks_bucket_t *aa = (ks_bucket_t *)a;
00102 const ks_bucket_t *bb = (ks_bucket_t *)b;
00103 #endif
00104 size_t len = aa->klen;
00105 int cmp;
00106 if (bb->klen < len)
00107 len = bb->klen;
00108 cmp = memcmp(aa->key, bb->key, len);
00109 if (cmp != 0)
00110 return cmp;
00111 return bb->klen - aa->klen;
00112 }
00113
00124 static void
00125 ks_assoc_bappend(ks_string_t *r, ks_base_t *b)
00126 {
00127 ks_assoc_t *s = KS_CAST(ks_assoc, b);
00128 ks_array_t *a = &(s->array);
00129 int i;
00130 ks_string_append(r, "d", 1);
00131 ks_array_sort(a, ks_bucket_keycompare);
00132 for (i = 0; i < ks_array_length(a); i++)
00133 ks_bappend(r, ks_array_get(a, i));
00134 ks_string_append(r, "e", 1);
00135 }
00136
00140 static ks_type_t ks_type_bucket = {
00141 "ks_bucket",
00142 (ks_destroy_t)ks_bucket_free,
00143 (ks_bappend_t)ks_bucket_bappend
00144 };
00145
00151 static ks_type_t *
00152 ks_bucket_type(void)
00153 {
00154 return &ks_type_bucket;
00155 }
00156
00160 static ks_type_t ks_type_assoc = {
00161 "ks_assoc",
00162 (ks_destroy_t)ks_assoc_free,
00163 (ks_bappend_t)ks_assoc_bappend
00164 };
00165
00171 ks_type_t *
00172 ks_assoc_type(void)
00173 {
00174 return &ks_type_assoc;
00175 }
00176
00187 static ks_bucket_t *
00188 ks_bucket_new(const char *key, size_t len, ks_base_t *data)
00189 {
00190 ks_bucket_t *b = (ks_bucket_t *)ks_malloc(sizeof(ks_bucket_t));
00191 b->base.type = &ks_type_bucket;
00192 b->key = (char *) ks_malloc(len);
00193 b->klen = len;
00194 memcpy(b->key, key, len);
00195 b->data = data;
00196 return b;
00197 }
00198
00209 void
00210 ks_assoc_init(ks_assoc_t *s)
00211 {
00212 s->base.type = &ks_type_assoc;
00213 ks_array_init(&(s->array));
00214 }
00215
00221 ks_assoc_t *
00222 ks_assoc_new(void)
00223 {
00224 ks_assoc_t *s = (ks_assoc_t *)ks_malloc(sizeof(ks_assoc_t));
00225 ks_assoc_init(s);
00226 return s;
00227 }
00228
00237 void
00238 ks_assoc_fini(ks_assoc_t *s)
00239 {
00240 ks_array_fini(&(s->array));
00241 }
00242
00250 void
00251 ks_assoc_free(ks_assoc_t *s)
00252 {
00253 ks_assoc_fini(s);
00254 ks_free(s);
00255 }
00256
00267 static ks_bucket_t *
00268 ks_assoc_bucket_find(ks_assoc_t *s, const char *key, size_t klen)
00269 {
00270 ks_array_t *a = &(s->array);
00271 int i;
00272 for (i = 0; i < ks_array_length(a); i++) {
00273 ks_bucket_t *b = KS_CAST(ks_bucket, ks_array_get(a, i));
00274 if (klen == b->klen)
00275 if (memcmp(key, b->key, b->klen) == 0)
00276 return b;
00277 }
00278 return NULL;
00279 }
00280
00294 void
00295 ks_assoc_put(ks_assoc_t *s, const char *key, size_t len, ks_base_t *ptr)
00296 {
00297 ks_bucket_t *b = ks_assoc_bucket_find(s, key, len);
00298 if (b == NULL) {
00299 ks_array_t *a = &(s->array);
00300 b = ks_bucket_new(key, len, ptr);
00301 ks_array_add(a, (ks_base_t *)b);
00302 }
00303 else {
00304 ks_destroy(b->data);
00305 b->data = ptr;
00306 }
00307 }
00308
00318 ks_base_t *
00319 ks_assoc_get(ks_assoc_t *s, const char *key, size_t len)
00320 {
00321 ks_bucket_t *b = ks_assoc_bucket_find(s, key, len);
00322 if (b == NULL)
00323 return NULL;
00324 return b->data;
00325 }
00326
00334 int
00335 ks_assoc_size(ks_assoc_t *s)
00336 {
00337 ks_array_t *a = &(s->array);
00338 return ks_array_length(a);
00339 }
00340
00349 ks_array_t *
00350 ks_assoc_keys(ks_assoc_t *s)
00351 {
00352 ks_array_t *a = &(s->array);
00353 ks_array_t *o = ks_array_new();
00354 int i;
00355 for (i = 0; i < ks_array_length(a); i++) {
00356 ks_bucket_t *b = KS_CAST(ks_bucket, ks_array_get(a, i));
00357 ks_string_t *r = ks_string_new(b->key, b->klen);
00358 ks_array_add(o, (ks_base_t *)r);
00359 }
00360 return o;
00361 }