]> pd.if.org Git - lice/blob - util.c
autocommit for files dated 2014-11-17 20:15:26
[lice] / util.c
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6
7 #include "util.h"
8
9 #define MEMORY 0x8000000
10
11 static unsigned char *memory_pool = NULL;
12 static size_t         memory_next = 0;
13
14 static void memory_cleanup(void) {
15     free(memory_pool);
16 }
17
18 void *memory_allocate(size_t bytes) {
19     void *value;
20
21     if (!memory_pool) {
22         memory_pool = malloc(MEMORY);
23         atexit(memory_cleanup);
24     }
25
26     if (memory_next > MEMORY)
27         goto bail;
28
29     value = &memory_pool[memory_next];
30     memory_next += bytes;
31
32     if (memory_next > MEMORY) {
33 bail:
34         fprintf(stderr, "[lice] out of memory");
35         exit(EXIT_FAILURE);
36     }
37
38     return value;
39 }
40
41 struct string_s {
42     char *buffer;
43     int   allocated;
44     int   length;
45 };
46
47 static void string_reallocate(string_t *string) {
48     int   size   = string->allocated * 2;
49     char *buffer = memory_allocate(size);
50
51     strcpy(buffer, string->buffer);
52     string->buffer    = buffer;
53     string->allocated = size;
54 }
55
56 void string_catf(string_t *string, const char *fmt, ...) {
57     va_list  va;
58     for (;;) {
59         int left  = string->allocated - string->length;
60         int write;
61
62         va_start(va, fmt);
63         write = vsnprintf(string->buffer + string->length, left, fmt, va);
64         va_end(va);
65
66         if (left <= write) {
67             string_reallocate(string);
68             continue;
69         }
70         string->length += write;
71         return;
72     }
73 }
74
75 string_t *string_create(void) {
76     string_t *string  = memory_allocate(sizeof(string_t));
77     string->buffer    = memory_allocate(8);
78     string->allocated = 8;
79     string->length    = 0;
80     string->buffer[0] = '\0';
81     return string;
82 }
83
84 char *string_buffer(string_t *string) {
85     return string->buffer;
86 }
87
88 void string_cat(string_t *string, char ch) {
89     if (string->allocated == (string->length + 1))
90         string_reallocate(string);
91     string->buffer[string->length++] = ch;
92     string->buffer[string->length]   = '\0';
93 }
94
95 char *string_quote(char *p) {
96     string_t *string = string_create();
97     while (*p) {
98         if (*p == '\"' || *p == '\\')
99             string_catf(string, "\\%c", *p);
100         else if (*p == '\n')
101             string_catf(string, "\\n");
102         else
103             string_cat(string, *p);
104         p++;
105     }
106     return string->buffer;
107 }
108
109 size_t string_length(string_t *string) {
110     return (string) ? string->length : 0;
111 }
112
113 typedef struct {
114     char *key;
115     void *value;
116 } table_entry_t;
117
118 void *table_create(void *parent) {
119     table_t *table = memory_allocate(sizeof(table_t));
120     table->list    = list_create();
121     table->parent  = parent;
122
123     return table;
124 }
125
126 void *table_find(table_t *table, const char *key) {
127     for (; table; table = table->parent) {
128         for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); ) {
129             table_entry_t *entry = list_iterator_next(it);
130             if (!strcmp(key, entry->key))
131                 return entry->value;
132         }
133     }
134     return NULL;
135 }
136
137 void table_insert(table_t *table, char *key, void *value) {
138     table_entry_t *entry = memory_allocate(sizeof(table_entry_t));
139     entry->key           = key;
140     entry->value         = value;
141
142     list_push(table->list, entry);
143 }
144
145 void *table_parent(table_t *table) {
146     return table->parent;
147 }
148
149 list_t *table_values(table_t *table) {
150     list_t *list = list_create();
151     for (; table; table = table->parent)
152         for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); )
153             list_push(list, ((table_entry_t*)list_iterator_next(it))->value);
154     return list;
155 }
156
157 list_t *table_keys(table_t *table) {
158     list_t *list = list_create();
159     for (; table; table = table->parent)
160         for (list_iterator_t *it = list_iterator(table->list); !list_iterator_end(it); )
161             list_push(list, ((table_entry_t*)list_iterator_next(it))->key);
162     return list;
163 }
164
165 pair_t *pair_create(void *first, void *second) {
166     pair_t *pair = memory_allocate(sizeof(pair_t));
167     pair->first  = first;
168     pair->second = second;
169     return pair;
170 }
171
172 int strcasecmp(const char *s1, const char *s2) {
173     const unsigned char *u1 = (const unsigned char *)s1;
174     const unsigned char *u2 = (const unsigned char *)s2;
175
176     while (tolower(*u1) == tolower(*u2++))
177         if(*u1++ == '\0')
178             return 0;
179     return tolower(*u1) - tolower(*--u2);
180 }
181
182 int strncasecmp(const char *s1, const char *s2, size_t n) {
183     const unsigned char *u1 = (const unsigned char *)s1;
184     const unsigned char *u2 = (const unsigned char *)s2;
185
186     if (!n)
187         return 0;
188
189     do {
190         if (tolower(*u1) != tolower(*u2++))
191             return tolower(*u1) - tolower(*--u2);
192         if (*u1++ == '\0')
193             break;
194     } while (--n != 0);
195
196     return 0;
197 }
198
199 size_t getline(char **line, size_t *n, FILE *stream) {
200     char *buf = NULL;
201     char *p   = buf;
202
203     int   size;
204     int   c;
205
206     if (!line)
207         return -1;
208     if (!stream)
209         return -1;
210     if (!n)
211         return -1;
212
213     buf  = *line;
214     size = *n;
215
216     if ((c = fgetc(stream)) == EOF)
217         return -1;
218     if (!buf) {
219         buf  = malloc(128);
220         size = 128;
221     }
222     p = buf;
223     while(c != EOF) {
224         if ((p - buf) > (size - 1)) {
225             size = size + 128;
226             buf  = realloc(buf, size);
227         }
228         *p++ = c;
229         if (c == '\n')
230             break;
231         c = fgetc(stream);
232     }
233
234     *p++  = '\0';
235     *line = buf;
236     *n    = size;
237
238     return p - buf - 1;
239 }