]>
git.ipfire.org Git - location/libloc.git/blob - src/stringpool.c
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
25 #include <loc/libloc.h>
26 #include <loc/format.h>
27 #include <loc/private.h>
28 #include <loc/stringpool.h>
30 enum loc_stringpool_mode
{
35 struct loc_stringpool
{
39 enum loc_stringpool_mode mode
;
47 static off_t
loc_stringpool_get_offset(struct loc_stringpool
* pool
, const char* pos
) {
51 if (pos
> (pool
->data
+ pool
->length
))
54 return pos
- pool
->data
;
57 static char* __loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
58 if (offset
< 0 || offset
>= pool
->length
)
61 return pool
->data
+ offset
;
64 static int loc_stringpool_grow(struct loc_stringpool
* pool
, size_t length
) {
65 DEBUG(pool
->ctx
, "Growing string pool to %zu bytes\n", length
);
68 off_t pos
= loc_stringpool_get_offset(pool
, pool
->pos
);
70 // Reallocate data section
71 pool
->data
= realloc(pool
->data
, length
);
75 pool
->length
= length
;
78 pool
->pos
= __loc_stringpool_get(pool
, pos
);
83 static off_t
loc_stringpool_append(struct loc_stringpool
* pool
, const char* string
) {
87 DEBUG(pool
->ctx
, "Appending '%s' to string pool at %p\n", string
, pool
);
89 // Make sure we have enough space
90 int r
= loc_stringpool_grow(pool
, pool
->length
+ strlen(string
) + 1);
96 off_t offset
= loc_stringpool_get_offset(pool
, pool
->pos
);
98 // Copy string byte by byte
100 *pool
->pos
++ = *string
++;
102 // Terminate the string
108 static void loc_stringpool_free(struct loc_stringpool
* pool
) {
109 DEBUG(pool
->ctx
, "Releasing string pool %p\n", pool
);
112 switch (pool
->mode
) {
113 case STRINGPOOL_DEFAULT
:
118 case STRINGPOOL_MMAP
:
120 r
= munmap(pool
->data
, pool
->length
);
122 ERROR(pool
->ctx
, "Could not unmap data at %p: %s\n",
123 pool
->data
, strerror(errno
));
128 loc_unref(pool
->ctx
);
132 LOC_EXPORT
int loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
) {
133 struct loc_stringpool
* p
= calloc(1, sizeof(*p
));
137 p
->ctx
= loc_ref(ctx
);
141 p
->mode
= STRINGPOOL_DEFAULT
;
148 static int loc_stringpool_mmap(struct loc_stringpool
* pool
, FILE* f
, size_t length
, off_t offset
) {
149 if (pool
->mode
!= STRINGPOOL_MMAP
)
152 DEBUG(pool
->ctx
, "Reading string pool starting from %jd (%zu bytes)\n", (intmax_t)offset
, length
);
154 // Map file content into memory
155 pool
->data
= pool
->pos
= mmap(NULL
, length
, PROT_READ
,
156 MAP_PRIVATE
, fileno(f
), offset
);
158 // Store size of section
159 pool
->length
= length
;
161 if (pool
->data
== MAP_FAILED
)
167 LOC_EXPORT
int loc_stringpool_open(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
,
168 FILE* f
, size_t length
, off_t offset
) {
169 struct loc_stringpool
* p
= NULL
;
171 // Allocate a new stringpool
172 int r
= loc_stringpool_new(ctx
, &p
);
176 // Change mode to mmap
177 p
->mode
= STRINGPOOL_MMAP
;
179 // Map data into memory
181 r
= loc_stringpool_mmap(p
, f
, length
, offset
);
183 loc_stringpool_free(p
);
192 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_ref(struct loc_stringpool
* pool
) {
198 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_unref(struct loc_stringpool
* pool
) {
199 if (--pool
->refcount
> 0)
202 loc_stringpool_free(pool
);
207 static off_t
loc_stringpool_get_next_offset(struct loc_stringpool
* pool
, off_t offset
) {
208 const char* string
= loc_stringpool_get(pool
, offset
);
212 return offset
+ strlen(string
) + 1;
215 LOC_EXPORT
const char* loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
216 return __loc_stringpool_get(pool
, offset
);
219 LOC_EXPORT
size_t loc_stringpool_get_size(struct loc_stringpool
* pool
) {
220 return loc_stringpool_get_offset(pool
, pool
->pos
);
223 static off_t
loc_stringpool_find(struct loc_stringpool
* pool
, const char* s
) {
228 while (offset
< pool
->length
) {
229 const char* string
= loc_stringpool_get(pool
, offset
);
233 int r
= strcmp(s
, string
);
237 offset
= loc_stringpool_get_next_offset(pool
, offset
);
243 LOC_EXPORT off_t
loc_stringpool_add(struct loc_stringpool
* pool
, const char* string
) {
244 off_t offset
= loc_stringpool_find(pool
, string
);
246 DEBUG(pool
->ctx
, "Found '%s' at position %jd\n", string
, (intmax_t)offset
);
250 return loc_stringpool_append(pool
, string
);
253 LOC_EXPORT
void loc_stringpool_dump(struct loc_stringpool
* pool
) {
256 while (offset
< pool
->length
) {
257 const char* string
= loc_stringpool_get(pool
, offset
);
261 printf("%jd (%zu): %s\n", (intmax_t)offset
, strlen(string
), string
);
263 offset
= loc_stringpool_get_next_offset(pool
, offset
);
267 LOC_EXPORT
size_t loc_stringpool_write(struct loc_stringpool
* pool
, FILE* f
) {
268 size_t size
= loc_stringpool_get_size(pool
);
270 return fwrite(pool
->data
, sizeof(*pool
->data
), size
, f
);