]>
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 LOC_EXPORT
int loc_stringpool_new(struct loc_ctx
* ctx
, struct loc_stringpool
** pool
, size_t max_length
) {
41 struct loc_stringpool
* p
= calloc(1, sizeof(*p
));
45 p
->ctx
= loc_ref(ctx
);
47 p
->max_length
= max_length
;
49 // Allocate the data section
50 p
->data
= malloc(p
->max_length
);
53 DEBUG(p
->ctx
, "String pool allocated at %p\n", p
);
54 DEBUG(p
->ctx
, " Maximum size: %zu bytes\n", p
->max_length
);
60 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_ref(struct loc_stringpool
* pool
) {
66 static void loc_stringpool_free(struct loc_stringpool
* pool
) {
67 DEBUG(pool
->ctx
, "Releasing string pool %p\n", pool
);
75 LOC_EXPORT
struct loc_stringpool
* loc_stringpool_unref(struct loc_stringpool
* pool
) {
76 if (--pool
->refcount
> 0)
79 loc_stringpool_free(pool
);
84 static off_t
loc_stringpool_get_offset(struct loc_stringpool
* pool
, const char* pos
) {
88 if (pos
> (pool
->data
+ pool
->max_length
))
91 return pos
- pool
->data
;
94 static off_t
loc_stringpool_get_next_offset(struct loc_stringpool
* pool
, off_t offset
) {
95 const char* string
= loc_stringpool_get(pool
, offset
);
97 return offset
+ strlen(string
) + 1;
100 static size_t loc_stringpool_space_left(struct loc_stringpool
* pool
) {
101 return pool
->max_length
- loc_stringpool_get_offset(pool
, pool
->pos
);
104 LOC_EXPORT
const char* loc_stringpool_get(struct loc_stringpool
* pool
, off_t offset
) {
105 if (offset
>= (ssize_t
)pool
->max_length
)
108 const char* string
= pool
->data
+ offset
;
110 // If the string is empty, we have reached the end
117 static off_t
loc_stringpool_find(struct loc_stringpool
* pool
, const char* s
) {
122 while (offset
< pool
->max_length
) {
123 const char* string
= loc_stringpool_get(pool
, offset
);
127 int r
= strcmp(s
, string
);
131 offset
= loc_stringpool_get_next_offset(pool
, offset
);
137 static off_t
loc_stringpool_append(struct loc_stringpool
* pool
, const char* string
) {
138 if (!string
|| !*string
)
141 DEBUG(pool
->ctx
, "Appending '%s' to string pool at %p\n", string
, pool
);
143 // Check if we have enough space left
144 size_t l
= strlen(string
) + 1;
145 if (l
> loc_stringpool_space_left(pool
)) {
146 DEBUG(pool
->ctx
, "Not enough space to append '%s'\n", string
);
147 DEBUG(pool
->ctx
, " Need %zu bytes but only have %zu\n", l
, loc_stringpool_space_left(pool
));
151 off_t offset
= loc_stringpool_get_offset(pool
, pool
->pos
);
153 // Copy string byte by byte
154 while (*string
&& loc_stringpool_space_left(pool
) > 1) {
155 *pool
->pos
++ = *string
++;
158 // Terminate the string
164 LOC_EXPORT off_t
loc_stringpool_add(struct loc_stringpool
* pool
, const char* string
) {
165 off_t offset
= loc_stringpool_find(pool
, string
);
167 DEBUG(pool
->ctx
, "Found '%s' at position %jd\n", string
, offset
);
171 return loc_stringpool_append(pool
, string
);
174 LOC_EXPORT
void loc_stringpool_dump(struct loc_stringpool
* pool
) {
177 while (offset
< pool
->max_length
) {
178 const char* string
= loc_stringpool_get(pool
, offset
);
182 printf("%jd (%zu): %s\n", offset
, strlen(string
), string
);
184 offset
= loc_stringpool_get_next_offset(pool
, offset
);