]>
git.ipfire.org Git - people/ms/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.
23 #include <loc/libloc.h>
24 #include "libloc-private.h"
25 #include "stringpool.h"
27 struct loc_stringpool
{
37 static int loc_stringpool_allocate(struct loc_stringpool
* pool
, size_t length
) {
42 pool
->max_length
= length
;
43 DEBUG(pool
->ctx
, "Allocating pool of %zu bytes\n", pool
->max_length
);
45 if (pool
->max_length
> 0) {
46 pool
->data
= malloc(pool
->max_length
);
51 pool
->pos
= pool
->data
;
56 LOC_EXPORT
int loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
, size_t max_length
) {
57 struct loc_stringpool
* p
= calloc(1, sizeof(*p
));
61 p
->ctx
= loc_ref(ctx
);
64 // Allocate the data section
65 int r
= loc_stringpool_allocate(p
, max_length
);
67 loc_stringpool_unref(p
);
71 DEBUG(p
->ctx
, "String pool allocated at %p\n", p
);
72 DEBUG(p
->ctx
, " Maximum size: %zu bytes\n", p
->max_length
);
78 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_ref(struct loc_stringpool
* pool
) {
84 static void loc_stringpool_free(struct loc_stringpool
* pool
) {
85 DEBUG(pool
->ctx
, "Releasing string pool %p\n", pool
);
95 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_unref(struct loc_stringpool
* pool
) {
96 if (--pool
->refcount
> 0)
99 loc_stringpool_free(pool
);
104 static off_t
loc_stringpool_get_offset(struct loc_stringpool
* pool
, const char* pos
) {
105 if (pos
< pool
->data
)
108 if (pos
> (pool
->data
+ pool
->max_length
))
111 return pos
- pool
->data
;
114 static off_t
loc_stringpool_get_next_offset(struct loc_stringpool
* pool
, off_t offset
) {
115 const char* string
= loc_stringpool_get(pool
, offset
);
117 return offset
+ strlen(string
) + 1;
120 static size_t loc_stringpool_space_left(struct loc_stringpool
* pool
) {
121 return pool
->max_length
- loc_stringpool_get_size(pool
);
124 LOC_EXPORT
const char* loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
125 if (offset
>= (ssize_t
)pool
->max_length
)
128 const char* string
= pool
->data
+ offset
;
130 // If the string is empty, we have reached the end
137 LOC_EXPORT
size_t loc_stringpool_get_size(struct loc_stringpool
* pool
) {
138 return loc_stringpool_get_offset(pool
, pool
->pos
);
141 static off_t
loc_stringpool_find(struct loc_stringpool
* pool
, const char* s
) {
146 while (offset
< pool
->max_length
) {
147 const char* string
= loc_stringpool_get(pool
, offset
);
151 int r
= strcmp(s
, string
);
155 offset
= loc_stringpool_get_next_offset(pool
, offset
);
161 static off_t
loc_stringpool_append(struct loc_stringpool
* pool
, const char* string
) {
162 if (!string
|| !*string
)
165 DEBUG(pool
->ctx
, "Appending '%s' to string pool at %p\n", string
, pool
);
167 // Check if we have enough space left
168 size_t l
= strlen(string
) + 1;
169 if (l
> loc_stringpool_space_left(pool
)) {
170 DEBUG(pool
->ctx
, "Not enough space to append '%s'\n", string
);
171 DEBUG(pool
->ctx
, " Need %zu bytes but only have %zu\n", l
, loc_stringpool_space_left(pool
));
175 off_t offset
= loc_stringpool_get_offset(pool
, pool
->pos
);
177 // Copy string byte by byte
178 while (*string
&& loc_stringpool_space_left(pool
) > 1) {
179 *pool
->pos
++ = *string
++;
182 // Terminate the string
188 LOC_EXPORT off_t
loc_stringpool_add(struct loc_stringpool
* pool
, const char* string
) {
189 off_t offset
= loc_stringpool_find(pool
, string
);
191 DEBUG(pool
->ctx
, "Found '%s' at position %jd\n", string
, offset
);
195 return loc_stringpool_append(pool
, string
);
198 LOC_EXPORT
void loc_stringpool_dump(struct loc_stringpool
* pool
) {
201 while (offset
< pool
->max_length
) {
202 const char* string
= loc_stringpool_get(pool
, offset
);
206 printf("%jd (%zu): %s\n", offset
, strlen(string
), string
);
208 offset
= loc_stringpool_get_next_offset(pool
, offset
);
212 LOC_EXPORT
int loc_stringpool_read(struct loc_stringpool
* pool
, FILE* f
, off_t offset
, size_t length
) {
213 // Allocate enough space
214 int r
= loc_stringpool_allocate(pool
, length
);
218 DEBUG(pool
->ctx
, "Reading string pool from %zu\n", offset
);
220 // Seek to the right offset
221 r
= fseek(f
, offset
, SEEK_SET
);
225 size_t bytes_read
= fread(pool
->data
, sizeof(*pool
->data
), length
, f
);
226 if (bytes_read
< length
) {
227 ERROR(pool
->ctx
, "Could not read pool. Only read %zu bytes\n", bytes_read
);
231 DEBUG(pool
->ctx
, "Read pool of %zu bytes\n", length
);
236 LOC_EXPORT
size_t loc_stringpool_write(struct loc_stringpool
* pool
, FILE* f
) {
237 size_t size
= loc_stringpool_get_size(pool
);
239 return fwrite(pool
->data
, sizeof(*pool
->data
), size
, f
);