/* libanode: the Anode C reference implementation * Copyright (C) 2009-2010 Adam Ierymenko * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "dictionary.h" static const char *EMPTY_STR = ""; void AnodeDictionary_clear(struct AnodeDictionary *d) { struct AnodeDictionaryEntry *e,*ne; int oldcs; unsigned int i; oldcs = d->case_sensitive; for(i=0;iht[i]; while (e) { ne = e->next; if ((e->key)&&(e->key != EMPTY_STR)) free((void *)e->key); if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value); free((void *)e); e = ne; } } Anode_zero((void *)d,sizeof(struct AnodeDictionary)); d->case_sensitive = oldcs; } void AnodeDictionary_put(struct AnodeDictionary *d,const char *key,const char *value) { struct AnodeDictionaryEntry *e; char *p1; const char *p2; unsigned int bucket = (d->case_sensitive) ? AnodeDictionary__get_bucket(key) : AnodeDictionary__get_bucket_ci(key); unsigned int len,i; e = d->ht[bucket]; while (e) { if (((d->case_sensitive) ? Anode_streq(key,e->key) : Anode_strcaseeq(key,e->key))) { if (!d->case_sensitive) { p1 = e->key; p2 = key; while (*p2) *(p1++) = *(p2++); } len = 0; while (value[len]) ++len; if (len) { if ((e->value)&&(e->value != EMPTY_STR)) e->value = (char *)realloc((void *)e->value,len + 1); else e->value = (char *)malloc(len + 1); for(i=0;ivalue[i] = value[i]; e->value[i] = (char)0; } else { if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value); e->value = (char *)EMPTY_STR; } return; } e = e->next; } e = (struct AnodeDictionaryEntry *)malloc(sizeof(struct AnodeDictionaryEntry)); len = 0; while (key[len]) ++len; if (len) { e->key = (char *)malloc(len + 1); for(i=0;ikey[i] = key[i]; e->key[i] = (char)0; } else e->key = (char *)EMPTY_STR; len = 0; while (value[len]) ++len; if (len) { e->value = (char *)malloc(len + 1); for(i=0;ivalue[i] = value[i]; e->value[i] = (char)0; } else e->value = (char *)EMPTY_STR; e->next = d->ht[bucket]; d->ht[bucket] = e; ++d->size; } void AnodeDictionary_read( struct AnodeDictionary *d, char *in, const char *line_breaks, const char *kv_breaks, const char *comment_chars, char escape_char, int trim_whitespace_from_keys, int trim_whitespace_from_values) { char *line = in; char *key; char *value; char *p1,*p2,*p3; char last = ~escape_char; int eof_state = 0; for(;;) { if ((!*in)||((Anode_strchr(line_breaks,*in))&&((last != escape_char)||(!escape_char)))) { if (!*in) eof_state = 1; else *in = (char)0; if ((*line)&&((comment_chars)&&(!Anode_strchr(comment_chars,*line)))) { key = line; while (*line) { if ((Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char))) { *(line++) = (char)0; break; } else last = *(line++); } while ((*line)&&(Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char))) last = *(line++); value = line; if (escape_char) { p1 = key; while (*p1) { if (*p1 == escape_char) { p2 = p1; p3 = p1 + 1; while (*p3) *(p2++) = *(p3++); *p2 = (char)0; } ++p1; } p1 = value; while (*p1) { if (*p1 == escape_char) { p2 = p1; p3 = p1 + 1; while (*p3) *(p2++) = *(p3++); *p2 = (char)0; } ++p1; } } if (trim_whitespace_from_keys) Anode_trim(key); if (trim_whitespace_from_values) Anode_trim(value); AnodeDictionary_put(d,key,value); } if (eof_state) break; else line = in + 1; } last = *(in++); } } long AnodeDictionary_write( struct AnodeDictionary *d, char *out, long out_size, const char *line_break, const char *kv_break) { struct AnodeDictionaryEntry *e; const char *tmp; long ptr = 0; unsigned int bucket; if (out_size <= 0) return -1; for(bucket=0;bucketht[bucket]; while (e) { tmp = e->key; if (tmp) { while (*tmp) { out[ptr++] = *tmp++; if (ptr >= (out_size - 1)) return -1; } } tmp = kv_break; if (tmp) { while (*tmp) { out[ptr++] = *tmp++; if (ptr >= (out_size - 1)) return -1; } } tmp = e->value; if (tmp) { while (*tmp) { out[ptr++] = *tmp++; if (ptr >= (out_size - 1)) return -1; } } tmp = line_break; if (tmp) { while (*tmp) { out[ptr++] = *tmp++; if (ptr >= (out_size - 1)) return -1; } } e = e->next; } } out[ptr] = (char)0; return ptr; }