]>
git.ipfire.org Git - location/libloc.git/blob - src/stringpool.c
6468c5e8f07889aec976601382f706a7c4d38673
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 int __loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
, enum loc_stringpool_mode mode
) {
48 struct loc_stringpool
* p
= calloc(1, sizeof(*p
));
52 p
->ctx
= loc_ref(ctx
);
63 LOC_EXPORT
int loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
) {
64 return __loc_stringpool_new(ctx
, pool
, STRINGPOOL_DEFAULT
);
67 static int loc_stringpool_mmap(struct loc_stringpool
* pool
, FILE* f
, size_t length
, off_t offset
) {
68 if (pool
->mode
!= STRINGPOOL_MMAP
)
71 DEBUG(pool
->ctx
, "Reading string pool starting from %zu (%zu bytes)\n", offset
, length
);
73 // Map file content into memory
74 pool
->data
= pool
->pos
= mmap(NULL
, length
, PROT_READ
,
75 MAP_PRIVATE
, fileno(f
), offset
);
77 // Store size of section
78 pool
->length
= length
;
80 if (pool
->data
== MAP_FAILED
)
86 LOC_EXPORT
int loc_stringpool_open(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
,
87 FILE* f
, size_t length
, off_t offset
) {
88 int r
= __loc_stringpool_new(ctx
, pool
, STRINGPOOL_MMAP
);
92 // Map data into memory
94 r
= loc_stringpool_mmap(*pool
, f
, length
, offset
);
102 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_ref(struct loc_stringpool
* pool
) {
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
struct loc_stringpool
* loc_stringpool_unref(struct loc_stringpool
* pool
) {
133 if (--pool
->refcount
> 0)
136 loc_stringpool_free(pool
);
141 static off_t
loc_stringpool_get_offset(struct loc_stringpool
* pool
, const char* pos
) {
142 if (pos
< pool
->data
)
145 if (pos
> (pool
->data
+ pool
->length
))
148 return pos
- pool
->data
;
151 static off_t
loc_stringpool_get_next_offset(struct loc_stringpool
* pool
, off_t offset
) {
152 const char* string
= loc_stringpool_get(pool
, offset
);
154 return offset
+ strlen(string
) + 1;
157 static char* __loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
158 if (offset
< 0 || offset
>= pool
->length
)
161 return pool
->data
+ offset
;
164 LOC_EXPORT
const char* loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
165 return __loc_stringpool_get(pool
, offset
);
168 LOC_EXPORT
size_t loc_stringpool_get_size(struct loc_stringpool
* pool
) {
169 return loc_stringpool_get_offset(pool
, pool
->pos
);
172 static off_t
loc_stringpool_find(struct loc_stringpool
* pool
, const char* s
) {
177 while (offset
< pool
->length
) {
178 const char* string
= loc_stringpool_get(pool
, offset
);
182 int r
= strcmp(s
, string
);
186 offset
= loc_stringpool_get_next_offset(pool
, offset
);
192 static int loc_stringpool_grow(struct loc_stringpool
* pool
, size_t length
) {
193 DEBUG(pool
->ctx
, "Growing string pool to %zu bytes\n", length
);
196 off_t pos
= loc_stringpool_get_offset(pool
, pool
->pos
);
198 // Reallocate data section
199 pool
->data
= realloc(pool
->data
, length
);
203 pool
->length
= length
;
206 pool
->pos
= __loc_stringpool_get(pool
, pos
);
211 static off_t
loc_stringpool_append(struct loc_stringpool
* pool
, const char* string
) {
212 if (!string
|| !*string
)
215 DEBUG(pool
->ctx
, "Appending '%s' to string pool at %p\n", string
, pool
);
217 // Make sure we have enough space
218 int r
= loc_stringpool_grow(pool
, pool
->length
+ strlen(string
) + 1);
224 off_t offset
= loc_stringpool_get_offset(pool
, pool
->pos
);
226 // Copy string byte by byte
228 *pool
->pos
++ = *string
++;
230 // Terminate the string
236 LOC_EXPORT off_t
loc_stringpool_add(struct loc_stringpool
* pool
, const char* string
) {
237 off_t offset
= loc_stringpool_find(pool
, string
);
239 DEBUG(pool
->ctx
, "Found '%s' at position %jd\n", string
, offset
);
243 return loc_stringpool_append(pool
, string
);
246 LOC_EXPORT
void loc_stringpool_dump(struct loc_stringpool
* pool
) {
249 while (offset
< pool
->length
) {
250 const char* string
= loc_stringpool_get(pool
, offset
);
254 printf("%jd (%zu): %s\n", offset
, strlen(string
), string
);
256 offset
= loc_stringpool_get_next_offset(pool
, offset
);
260 LOC_EXPORT
size_t loc_stringpool_write(struct loc_stringpool
* pool
, FILE* f
) {
261 size_t size
= loc_stringpool_get_size(pool
);
263 return fwrite(pool
->data
, sizeof(*pool
->data
), size
, f
);