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 <libloc/libloc.h>
26 #include <libloc/format.h>
27 #include <libloc/private.h>
28 #include <libloc/stringpool.h>
30 #define LOC_STRINGPOOL_BLOCK_SIZE (512 * 1024)
32 struct loc_stringpool
{
36 // Reference to any mapped data
40 // Reference to own storage
45 static int loc_stringpool_grow(struct loc_stringpool
* pool
, const size_t size
) {
46 DEBUG(pool
->ctx
, "Growing string pool by %zu byte(s)\n", size
);
52 pool
->blocks
= realloc(pool
->blocks
, pool
->size
);
54 ERROR(pool
->ctx
, "Could not grow string pool: %m\n");
58 // Update data pointer
59 pool
->data
= pool
->blocks
;
64 static off_t
loc_stringpool_append(struct loc_stringpool
* pool
, const char* string
) {
70 DEBUG(pool
->ctx
, "Appending '%s' to string pool at %p\n", string
, pool
);
72 // How much space to we need?
73 const size_t length
= strlen(string
) + 1;
75 // Make sure we have enough space
76 if (pool
->length
+ length
> pool
->size
) {
77 int r
= loc_stringpool_grow(pool
, LOC_STRINGPOOL_BLOCK_SIZE
);
82 off_t offset
= pool
->length
;
85 memcpy(pool
->blocks
+ offset
, string
, length
);
87 // Update the length of the pool
88 pool
->length
+= length
;
93 static void loc_stringpool_free(struct loc_stringpool
* pool
) {
94 DEBUG(pool
->ctx
, "Releasing string pool %p\n", pool
);
100 loc_unref(pool
->ctx
);
104 int loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
) {
105 struct loc_stringpool
* p
= calloc(1, sizeof(*p
));
109 p
->ctx
= loc_ref(ctx
);
117 int loc_stringpool_open(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
,
118 const char* data
, const size_t length
) {
119 struct loc_stringpool
* p
= NULL
;
121 // Allocate a new stringpool
122 int r
= loc_stringpool_new(ctx
, &p
);
126 // Store data and length
130 DEBUG(p
->ctx
, "Opened string pool at %p (%zu bytes)\n", p
->data
, p
->length
);
137 loc_stringpool_free(p
);
142 struct loc_stringpool
* loc_stringpool_ref(struct loc_stringpool
* pool
) {
148 struct loc_stringpool
* loc_stringpool_unref(struct loc_stringpool
* pool
) {
149 if (--pool
->refcount
> 0)
152 loc_stringpool_free(pool
);
157 const char* loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
159 if (offset
< 0 || offset
>= pool
->length
) {
164 // Return any data that we have in memory
165 return pool
->data
+ offset
;
168 size_t loc_stringpool_get_size(struct loc_stringpool
* pool
) {
172 static off_t
loc_stringpool_find(struct loc_stringpool
* pool
, const char* s
) {
179 while (offset
< pool
->length
) {
180 const char* string
= loc_stringpool_get(pool
, offset
);
187 if (strcmp(s
, string
) == 0)
191 offset
+= strlen(string
) + 1;
199 off_t
loc_stringpool_add(struct loc_stringpool
* pool
, const char* string
) {
200 off_t offset
= loc_stringpool_find(pool
, string
);
202 DEBUG(pool
->ctx
, "Found '%s' at position %jd\n", string
, (intmax_t)offset
);
206 return loc_stringpool_append(pool
, string
);
209 void loc_stringpool_dump(struct loc_stringpool
* pool
) {
212 while (offset
< pool
->length
) {
213 const char* string
= loc_stringpool_get(pool
, offset
);
217 printf("%jd (%zu): %s\n", (intmax_t)offset
, strlen(string
), string
);
220 offset
+= strlen(string
) + 1;
224 size_t loc_stringpool_write(struct loc_stringpool
* pool
, FILE* f
) {
225 size_t size
= loc_stringpool_get_size(pool
);
227 return fwrite(pool
->data
, sizeof(*pool
->data
), size
, f
);