1 /* Blerg is (C) 2011 The Dominion of Awesome, and is distributed under a
2 * BSD-style license. Please see the COPYING file for details.
13 #include <stringbucket.h>
15 #define STRINGBUCKET_STRINGSIZE 64
17 const char * strnchr(const char *s, int c, int n) {
28 int stringbucket_remap(struct stringbucket *sb) {
31 if (sb->list != NULL) {
32 munmap(sb->list, sb->size);
35 flock(sb->fd, LOCK_SH);
37 flock(sb->fd, LOCK_UN);
38 sb->size = st.st_size;
40 sb->list = mmap(NULL, sb->size, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0);
41 if (sb->list == MAP_FAILED) {
42 perror("stringbucket mmap");
46 /* Don't map anything for now. */
53 struct stringbucket * stringbucket_open(const char *filename) {
54 struct stringbucket *obj = malloc(sizeof(struct stringbucket));
59 perror("stringbucket allocate");
60 goto stringbucket_open__malloc_fail;
63 obj->fd = open(filename, O_RDWR | O_APPEND | O_CREAT, 0600);
65 perror("stringbucket open");
66 goto stringbucket_open__open_fail;
69 if (stringbucket_remap(obj) == 0) {
70 goto stringbucket_open__mmap_fail;
75 stringbucket_open__mmap_fail:
77 stringbucket_open__open_fail:
79 stringbucket_open__malloc_fail:
83 void stringbucket_close(struct stringbucket *sb) {
88 munmap(sb->list, sb->size);
94 int stringbucket_find(struct stringbucket *sb, const char *string) {
98 char * end = sb->list + sb->size;
99 int string_len = strlen(string);
101 char * ptr = sb->list;
103 char * next = (char *) strnchr(ptr, '\n', end - ptr);
106 int len = next - ptr;
107 if (len > STRINGBUCKET_STRINGSIZE)
108 len = STRINGBUCKET_STRINGSIZE;
109 if (memcmp(ptr, string, (len < string_len ? string_len : len)) == 0) {
110 return (ptr - sb->list);
118 int stringbucket_add(struct stringbucket *sb, const char *string) {
119 if (stringbucket_find(sb, string) != -1) return 0;
120 int str_len = strlen(string);
123 flock(sb->fd, LOCK_EX);
124 len = write(sb->fd, string, str_len);
126 perror("stringbucket add");
128 goto stringbucket_add__fail;
129 len = write(sb->fd, "\n", 1);
131 perror("stringbucket add");
133 goto stringbucket_add__fail;
134 flock(sb->fd, LOCK_UN);
136 /* remap the data to include added content */
137 if (stringbucket_remap(sb) == 0)
142 stringbucket_add__fail:
143 ftruncate(sb->fd, sb->size);
144 flock(sb->fd, LOCK_UN);
148 int stringbucket_delete(struct stringbucket *sb, const char *string) {
149 int pos = stringbucket_find(sb, string);
150 if (pos == -1) return 0;
152 /* We doin' it DOS style! */
157 void stringbucket_iterate(struct stringbucket *sb, void (*iter)(char *, void *), void *stuff) {
158 if (sb->list == NULL)
161 char string[STRINGBUCKET_STRINGSIZE + 1];
162 char * ptr = sb->list;
163 char * end = sb->list + sb->size;
166 char * next = (char *) strnchr(ptr, '\n', end - ptr);
173 int len = next - ptr;
174 memcpy(string, ptr, len);