geoip2_c 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +3 -4
- data/README.md +21 -3
- data/docker-compose.yml +15 -1
- data/dockerfiles/{Dockerfile-ruby2.1 → Dockerfile-ruby2.5} +1 -1
- data/dockerfiles/{Dockerfile-ruby2.2 → Dockerfile-ruby2.6} +1 -1
- data/ext/geoip2/geoip2.c +5 -3
- data/ext/geoip2/libmaxminddb/.gitignore +3 -0
- data/ext/geoip2/libmaxminddb/.travis.yml +24 -2
- data/ext/geoip2/libmaxminddb/Changes.md +39 -0
- data/ext/geoip2/libmaxminddb/README.dev.md +41 -30
- data/ext/geoip2/libmaxminddb/README.md +3 -3
- data/ext/geoip2/libmaxminddb/bin/Makefile.am +5 -0
- data/ext/geoip2/libmaxminddb/bin/mmdblookup.c +333 -15
- data/ext/geoip2/libmaxminddb/configure.ac +5 -5
- data/ext/geoip2/libmaxminddb/dev-bin/ppa-release.sh +8 -5
- data/ext/geoip2/libmaxminddb/dev-bin/release.sh +7 -0
- data/ext/geoip2/libmaxminddb/dev-bin/valgrind-all.pl +10 -3
- data/ext/geoip2/libmaxminddb/include/maxminddb.h +11 -2
- data/ext/geoip2/libmaxminddb/projects/VS12/libmaxminddb.vcxproj +3 -1
- data/ext/geoip2/libmaxminddb/projects/VS12/libmaxminddb.vcxproj.filters +7 -1
- data/ext/geoip2/libmaxminddb/src/Makefile.am +18 -2
- data/ext/geoip2/libmaxminddb/src/data-pool.c +180 -0
- data/ext/geoip2/libmaxminddb/src/data-pool.h +52 -0
- data/ext/geoip2/libmaxminddb/src/maxminddb.c +58 -48
- data/ext/geoip2/libmaxminddb/t/Makefile.am +6 -2
- data/ext/geoip2/libmaxminddb/t/bad_databases_t.c +1 -0
- data/ext/geoip2/libmaxminddb/t/basic_lookup_t.c +35 -0
- data/ext/geoip2/libmaxminddb/t/data-pool-t.c +374 -0
- data/ext/geoip2/libmaxminddb/t/external_symbols_t.pl +106 -0
- data/lib/geoip2/version.rb +1 -1
- metadata +9 -7
- data/dockerfiles/Dockerfile-ruby2.3 +0 -8
@@ -2,7 +2,7 @@
|
|
2
2
|
# Process this file with autoconf to produce a configure script.
|
3
3
|
|
4
4
|
AC_PREREQ([2.63])
|
5
|
-
AC_INIT([libmaxminddb], [1.2
|
5
|
+
AC_INIT([libmaxminddb], [1.3.2], [support@maxmind.com])
|
6
6
|
AC_CONFIG_SRCDIR([include/maxminddb.h])
|
7
7
|
AC_CONFIG_HEADERS([config.h include/maxminddb_config.h])
|
8
8
|
|
@@ -63,9 +63,11 @@ AC_CHECK_HEADERS([arpa/inet.h assert.h fcntl.h inttypes.h libgen.h math.h netdb.
|
|
63
63
|
# so we only run them on non MinGW-Systems. For MinGW we also need to link
|
64
64
|
# against ws2_32.
|
65
65
|
AC_CANONICAL_HOST
|
66
|
+
is_windows=false
|
66
67
|
case $host_os in
|
67
68
|
mingw*)
|
68
69
|
LDFLAGS="-lws2_32"
|
70
|
+
is_windows=true
|
69
71
|
;;
|
70
72
|
*)
|
71
73
|
AC_TYPE_OFF_T
|
@@ -77,6 +79,7 @@ case $host_os in
|
|
77
79
|
;;
|
78
80
|
esac
|
79
81
|
|
82
|
+
AM_CONDITIONAL([WINDOWS], [test x$is_windows = xtrue])
|
80
83
|
|
81
84
|
# This check is backwards in order to make life easier for people writing
|
82
85
|
# extensions in other languages that link to this library. If they want to
|
@@ -94,15 +97,12 @@ AC_CHECK_TYPE(
|
|
94
97
|
|
95
98
|
AC_CHECK_TYPES([boolean])
|
96
99
|
|
97
|
-
|
98
|
-
[open_memstream],
|
99
|
-
[AC_DEFINE([HAVE_OPEN_MEMSTREAM], [1], [Has an open_memstream() function])])
|
100
|
+
AC_CHECK_FUNCS([clock_gettime open_memstream])
|
100
101
|
|
101
102
|
AC_C_BIGENDIAN(
|
102
103
|
[AC_DEFINE([MMDB_LITTLE_ENDIAN], [0], [System is big-endian])],
|
103
104
|
[AC_DEFINE([MMDB_LITTLE_ENDIAN], [1], [System is little-endian])])
|
104
105
|
|
105
|
-
AC_FUNC_MALLOC
|
106
106
|
AC_FUNC_MMAP
|
107
107
|
|
108
108
|
AC_SEARCH_LIBS([fabs], [m])
|
@@ -4,7 +4,7 @@ set -e
|
|
4
4
|
set -x
|
5
5
|
set -u
|
6
6
|
|
7
|
-
DISTS=(
|
7
|
+
DISTS=( artful zesty xenial trusty precise )
|
8
8
|
|
9
9
|
VERSION=$(perl -MFile::Slurp::Tiny=read_file -MDateTime <<EOF
|
10
10
|
use v5.16;
|
@@ -27,11 +27,11 @@ pushd "$SRCDIR"
|
|
27
27
|
git merge "$VERSION"
|
28
28
|
|
29
29
|
for dist in "${DISTS[@]}"; do
|
30
|
-
git clean -xfd
|
31
|
-
git reset HEAD --hard
|
32
|
-
|
33
30
|
dch -v "$VERSION-0+maxmind1~$dist" -D "$dist" -u low "New upstream release."
|
34
31
|
gbp buildpackage -S --git-ignore-new
|
32
|
+
|
33
|
+
git clean -xfd
|
34
|
+
git reset HEAD --hard
|
35
35
|
done
|
36
36
|
|
37
37
|
read -e -p "Release to PPA? (y/n)" SHOULD_RELEASE
|
@@ -41,9 +41,12 @@ if [ "$SHOULD_RELEASE" != "y" ]; then
|
|
41
41
|
exit 1
|
42
42
|
fi
|
43
43
|
|
44
|
+
# Upload to launchpad
|
44
45
|
dput ppa:maxmind/ppa ../*source.changes
|
45
46
|
|
46
|
-
|
47
|
+
# Make the changelog up to date in git
|
48
|
+
|
49
|
+
dch -v "$VERSION-0+maxmind1" -D "${DISTS[0]}" -u low "New upstream release."
|
47
50
|
|
48
51
|
git add debian/changelog
|
49
52
|
git commit -m "Update debian/changelog for $VERSION"
|
@@ -47,6 +47,13 @@ if [ -n "$(git status --porcelain)" ]; then
|
|
47
47
|
git commit -m "Bumped version to $version"
|
48
48
|
fi
|
49
49
|
|
50
|
+
./bootstrap
|
51
|
+
./configure
|
52
|
+
make
|
53
|
+
make check
|
54
|
+
make clean
|
55
|
+
make safedist
|
56
|
+
|
50
57
|
if [ ! -d .gh-pages ]; then
|
51
58
|
echo "Checking out gh-pages in .gh-pages"
|
52
59
|
git clone -b gh-pages git@github.com:maxmind/libmaxminddb.git .gh-pages
|
@@ -1,5 +1,10 @@
|
|
1
1
|
#!/usr/bin/env perl
|
2
2
|
|
3
|
+
# Note to run this you will probably want to build with ./configure
|
4
|
+
# --disable-shared. You don't want to valgrind the libtool script.
|
5
|
+
#
|
6
|
+
# Also make sure you compile the tests first (`make check').
|
7
|
+
|
3
8
|
use strict;
|
4
9
|
use warnings;
|
5
10
|
|
@@ -11,11 +16,13 @@ my $top_dir = "$Bin/..";
|
|
11
16
|
|
12
17
|
my $output;
|
13
18
|
|
14
|
-
my @tests
|
19
|
+
my @tests;
|
20
|
+
push @tests, glob "$top_dir/t/*_t";
|
21
|
+
push @tests, glob "$top_dir/t/*-t";
|
15
22
|
|
16
23
|
my @mmdblookup = (
|
17
24
|
"$top_dir/bin/mmdblookup",
|
18
|
-
'--file', "$top_dir/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb",
|
25
|
+
'--file', "$top_dir/t/maxmind-db/test-data/MaxMind-DB-test-decoder.mmdb",
|
19
26
|
'--ip',
|
20
27
|
);
|
21
28
|
|
@@ -31,7 +38,7 @@ my @cmds = (
|
|
31
38
|
for my $cmd (@cmds) {
|
32
39
|
my $output;
|
33
40
|
run3(
|
34
|
-
[ qw( valgrind --leak-check=full -- ), @{$cmd} ],
|
41
|
+
[ qw( valgrind -v --leak-check=full --show-leak-kinds=all -- ), @{$cmd} ],
|
35
42
|
\undef,
|
36
43
|
\$output,
|
37
44
|
\$output,
|
@@ -5,8 +5,16 @@ extern "C" {
|
|
5
5
|
#ifndef MAXMINDDB_H
|
6
6
|
#define MAXMINDDB_H
|
7
7
|
|
8
|
+
/* Request POSIX.1-2008. However, we want to remain compatible with
|
9
|
+
* POSIX.1-2001 (since we have been historically and see no reason to drop
|
10
|
+
* compatibility). By requesting POSIX.1-2008, we can conditionally use
|
11
|
+
* features provided by that standard if the implementation provides it. We can
|
12
|
+
* check for what the implementation provides by checking the _POSIX_VERSION
|
13
|
+
* macro after including unistd.h. If a feature is in POSIX.1-2008 but not
|
14
|
+
* POSIX.1-2001, check that macro before using the feature (or check for the
|
15
|
+
* feature directly if possible). */
|
8
16
|
#ifndef _POSIX_C_SOURCE
|
9
|
-
#define _POSIX_C_SOURCE
|
17
|
+
#define _POSIX_C_SOURCE 200809L
|
10
18
|
#endif
|
11
19
|
|
12
20
|
#include "maxminddb_config.h"
|
@@ -20,7 +28,7 @@ extern "C" {
|
|
20
28
|
#include <winsock2.h>
|
21
29
|
#include <ws2tcpip.h>
|
22
30
|
/* libmaxminddb package version from configure */
|
23
|
-
#define PACKAGE_VERSION "1.2
|
31
|
+
#define PACKAGE_VERSION "1.3.2"
|
24
32
|
|
25
33
|
typedef ADDRESS_FAMILY sa_family_t;
|
26
34
|
|
@@ -135,6 +143,7 @@ typedef struct MMDB_entry_data_s {
|
|
135
143
|
typedef struct MMDB_entry_data_list_s {
|
136
144
|
MMDB_entry_data_s entry_data;
|
137
145
|
struct MMDB_entry_data_list_s *next;
|
146
|
+
void *pool;
|
138
147
|
} MMDB_entry_data_list_s;
|
139
148
|
|
140
149
|
typedef struct MMDB_description_s {
|
@@ -20,9 +20,11 @@
|
|
20
20
|
</ItemGroup>
|
21
21
|
<ItemGroup>
|
22
22
|
<ClCompile Include="..\..\src\maxminddb.c" />
|
23
|
+
<ClCompile Include="..\..\src\data-pool.c" />
|
23
24
|
</ItemGroup>
|
24
25
|
<ItemGroup>
|
25
26
|
<ClInclude Include="..\..\include\maxminddb.h" />
|
27
|
+
<ClInclude Include="..\..\src\data-pool.h" />
|
26
28
|
</ItemGroup>
|
27
29
|
<ItemGroup>
|
28
30
|
<None Include="README" />
|
@@ -138,4 +140,4 @@
|
|
138
140
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
139
141
|
<ImportGroup Label="ExtensionTargets">
|
140
142
|
</ImportGroup>
|
141
|
-
</Project>
|
143
|
+
</Project>
|
@@ -14,13 +14,19 @@
|
|
14
14
|
<ClCompile Include="..\..\src\maxminddb.c">
|
15
15
|
<Filter>Source Files</Filter>
|
16
16
|
</ClCompile>
|
17
|
+
<ClCompile Include="..\..\src\data-pool.c">
|
18
|
+
<Filter>Source Files</Filter>
|
19
|
+
</ClCompile>
|
17
20
|
</ItemGroup>
|
18
21
|
<ItemGroup>
|
19
22
|
<ClInclude Include="..\..\include\maxminddb.h">
|
20
23
|
<Filter>Header Files</Filter>
|
21
24
|
</ClInclude>
|
25
|
+
<ClInclude Include="..\..\src\data-pool.h">
|
26
|
+
<Filter>Header Files</Filter>
|
27
|
+
</ClInclude>
|
22
28
|
</ItemGroup>
|
23
29
|
<ItemGroup>
|
24
30
|
<None Include="README" />
|
25
31
|
</ItemGroup>
|
26
|
-
</Project>
|
32
|
+
</Project>
|
@@ -2,8 +2,24 @@ include $(top_srcdir)/common.mk
|
|
2
2
|
|
3
3
|
lib_LTLIBRARIES = libmaxminddb.la
|
4
4
|
|
5
|
-
libmaxminddb_la_SOURCES = maxminddb.c maxminddb-compat-util.h
|
6
|
-
|
5
|
+
libmaxminddb_la_SOURCES = maxminddb.c maxminddb-compat-util.h \
|
6
|
+
data-pool.c data-pool.h
|
7
|
+
libmaxminddb_la_LDFLAGS = -version-info 0:7:0 -export-symbols-regex '^MMDB_.*'
|
7
8
|
include_HEADERS = $(top_srcdir)/include/maxminddb.h
|
8
9
|
|
9
10
|
pkgconfig_DATA = libmaxminddb.pc
|
11
|
+
|
12
|
+
TESTS = test-data-pool
|
13
|
+
|
14
|
+
check_PROGRAMS = test-data-pool
|
15
|
+
|
16
|
+
test_data_pool_SOURCES = data-pool.c data-pool.h
|
17
|
+
test_data_pool_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/t -DTEST_DATA_POOL
|
18
|
+
test_data_pool_LDADD = $(top_srcdir)/t/libmmdbtest.la \
|
19
|
+
$(top_srcdir)/t/libtap/libtap.a
|
20
|
+
|
21
|
+
$(top_srcdir)/t/libmmdbtest.la:
|
22
|
+
$(MAKE) -C $(top_srcdir)/t libmmdbtest.la
|
23
|
+
|
24
|
+
$(top_srcdir)/t/libtap/libtap.a:
|
25
|
+
$(MAKE) -C $(top_srcdir)/t/libtap libtap.a
|
@@ -0,0 +1,180 @@
|
|
1
|
+
#include "data-pool.h"
|
2
|
+
#include "maxminddb.h"
|
3
|
+
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <stddef.h>
|
6
|
+
#include <stdlib.h>
|
7
|
+
|
8
|
+
static bool can_multiply(size_t const, size_t const, size_t const);
|
9
|
+
|
10
|
+
// Allocate an MMDB_data_pool_s. It initially has space for size
|
11
|
+
// MMDB_entry_data_list_s structs.
|
12
|
+
MMDB_data_pool_s *data_pool_new(size_t const size)
|
13
|
+
{
|
14
|
+
MMDB_data_pool_s *const pool = calloc(1, sizeof(MMDB_data_pool_s));
|
15
|
+
if (!pool) {
|
16
|
+
return NULL;
|
17
|
+
}
|
18
|
+
|
19
|
+
if (size == 0 ||
|
20
|
+
!can_multiply(SIZE_MAX, size, sizeof(MMDB_entry_data_list_s))) {
|
21
|
+
data_pool_destroy(pool);
|
22
|
+
return NULL;
|
23
|
+
}
|
24
|
+
pool->size = size;
|
25
|
+
pool->blocks[0] = calloc(pool->size, sizeof(MMDB_entry_data_list_s));
|
26
|
+
if (!pool->blocks[0]) {
|
27
|
+
data_pool_destroy(pool);
|
28
|
+
return NULL;
|
29
|
+
}
|
30
|
+
pool->blocks[0]->pool = pool;
|
31
|
+
|
32
|
+
pool->sizes[0] = size;
|
33
|
+
|
34
|
+
pool->block = pool->blocks[0];
|
35
|
+
|
36
|
+
return pool;
|
37
|
+
}
|
38
|
+
|
39
|
+
// Determine if we can multiply m*n. We can do this if the result will be below
|
40
|
+
// the given max. max will typically be SIZE_MAX.
|
41
|
+
//
|
42
|
+
// We want to know if we'll wrap around.
|
43
|
+
static bool can_multiply(size_t const max, size_t const m, size_t const n)
|
44
|
+
{
|
45
|
+
if (m == 0) {
|
46
|
+
return false;
|
47
|
+
}
|
48
|
+
|
49
|
+
return n <= max / m;
|
50
|
+
}
|
51
|
+
|
52
|
+
// Clean up the data pool.
|
53
|
+
void data_pool_destroy(MMDB_data_pool_s *const pool)
|
54
|
+
{
|
55
|
+
if (!pool) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
for (size_t i = 0; i <= pool->index; i++) {
|
60
|
+
free(pool->blocks[i]);
|
61
|
+
}
|
62
|
+
|
63
|
+
free(pool);
|
64
|
+
}
|
65
|
+
|
66
|
+
// Claim a new struct from the pool. Doing this may cause the pool's size to
|
67
|
+
// grow.
|
68
|
+
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const pool)
|
69
|
+
{
|
70
|
+
if (!pool) {
|
71
|
+
return NULL;
|
72
|
+
}
|
73
|
+
|
74
|
+
if (pool->used < pool->size) {
|
75
|
+
MMDB_entry_data_list_s *const element = pool->block + pool->used;
|
76
|
+
pool->used++;
|
77
|
+
return element;
|
78
|
+
}
|
79
|
+
|
80
|
+
// Take it from a new block of memory.
|
81
|
+
|
82
|
+
size_t const new_index = pool->index + 1;
|
83
|
+
if (new_index == DATA_POOL_NUM_BLOCKS) {
|
84
|
+
// See the comment about not growing this on DATA_POOL_NUM_BLOCKS.
|
85
|
+
return NULL;
|
86
|
+
}
|
87
|
+
|
88
|
+
if (!can_multiply(SIZE_MAX, pool->size, 2)) {
|
89
|
+
return NULL;
|
90
|
+
}
|
91
|
+
size_t const new_size = pool->size * 2;
|
92
|
+
|
93
|
+
if (!can_multiply(SIZE_MAX, new_size, sizeof(MMDB_entry_data_list_s))) {
|
94
|
+
return NULL;
|
95
|
+
}
|
96
|
+
pool->blocks[new_index] = calloc(new_size, sizeof(MMDB_entry_data_list_s));
|
97
|
+
if (!pool->blocks[new_index]) {
|
98
|
+
return NULL;
|
99
|
+
}
|
100
|
+
|
101
|
+
// We don't need to set this, but it's useful for introspection in tests.
|
102
|
+
pool->blocks[new_index]->pool = pool;
|
103
|
+
|
104
|
+
pool->index = new_index;
|
105
|
+
pool->block = pool->blocks[pool->index];
|
106
|
+
|
107
|
+
pool->size = new_size;
|
108
|
+
pool->sizes[pool->index] = pool->size;
|
109
|
+
|
110
|
+
MMDB_entry_data_list_s *const element = pool->block;
|
111
|
+
pool->used = 1;
|
112
|
+
return element;
|
113
|
+
}
|
114
|
+
|
115
|
+
// Turn the structs in the array-like pool into a linked list.
|
116
|
+
//
|
117
|
+
// Before calling this function, the list isn't linked up.
|
118
|
+
MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const pool)
|
119
|
+
{
|
120
|
+
if (!pool) {
|
121
|
+
return NULL;
|
122
|
+
}
|
123
|
+
|
124
|
+
if (pool->index == 0 && pool->used == 0) {
|
125
|
+
return NULL;
|
126
|
+
}
|
127
|
+
|
128
|
+
for (size_t i = 0; i <= pool->index; i++) {
|
129
|
+
MMDB_entry_data_list_s *const block = pool->blocks[i];
|
130
|
+
|
131
|
+
size_t size = pool->sizes[i];
|
132
|
+
if (i == pool->index) {
|
133
|
+
size = pool->used;
|
134
|
+
}
|
135
|
+
|
136
|
+
for (size_t j = 0; j < size - 1; j++) {
|
137
|
+
MMDB_entry_data_list_s *const cur = block + j;
|
138
|
+
cur->next = block + j + 1;
|
139
|
+
}
|
140
|
+
|
141
|
+
if (i < pool->index) {
|
142
|
+
MMDB_entry_data_list_s *const last = block + size - 1;
|
143
|
+
last->next = pool->blocks[i + 1];
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
return pool->blocks[0];
|
148
|
+
}
|
149
|
+
|
150
|
+
#ifdef TEST_DATA_POOL
|
151
|
+
|
152
|
+
#include <libtap/tap.h>
|
153
|
+
#include <maxminddb_test_helper.h>
|
154
|
+
|
155
|
+
static void test_can_multiply(void);
|
156
|
+
|
157
|
+
int main(void)
|
158
|
+
{
|
159
|
+
plan(NO_PLAN);
|
160
|
+
test_can_multiply();
|
161
|
+
done_testing();
|
162
|
+
}
|
163
|
+
|
164
|
+
static void test_can_multiply(void)
|
165
|
+
{
|
166
|
+
{
|
167
|
+
ok(can_multiply(SIZE_MAX, 1, SIZE_MAX), "1*SIZE_MAX is ok");
|
168
|
+
}
|
169
|
+
|
170
|
+
{
|
171
|
+
ok(!can_multiply(SIZE_MAX, 2, SIZE_MAX), "2*SIZE_MAX is not ok");
|
172
|
+
}
|
173
|
+
|
174
|
+
{
|
175
|
+
ok(can_multiply(SIZE_MAX, 10240, sizeof(MMDB_entry_data_list_s)),
|
176
|
+
"1024 entry_data_list_s's are okay");
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
#endif
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#ifndef DATA_POOL_H
|
2
|
+
#define DATA_POOL_H
|
3
|
+
|
4
|
+
#include "maxminddb.h"
|
5
|
+
|
6
|
+
#include <stdbool.h>
|
7
|
+
#include <stddef.h>
|
8
|
+
|
9
|
+
// This should be large enough that we never need to grow the array of pointers
|
10
|
+
// to blocks. 32 is enough. Even starting out of with size 1 (1 struct), the
|
11
|
+
// 32nd element alone will provide 2**32 structs as we exponentially increase
|
12
|
+
// the number in each block. Being confident that we do not have to grow the
|
13
|
+
// array lets us avoid writing code to do that. That code would be risky as it
|
14
|
+
// would rarely be hit and likely not be well tested.
|
15
|
+
#define DATA_POOL_NUM_BLOCKS 32
|
16
|
+
|
17
|
+
// A pool of memory for MMDB_entry_data_list_s structs. This is so we can
|
18
|
+
// allocate multiple up front rather than one at a time for performance
|
19
|
+
// reasons.
|
20
|
+
//
|
21
|
+
// The order you add elements to it (by calling data_pool_alloc()) ends up as
|
22
|
+
// the order of the list.
|
23
|
+
//
|
24
|
+
// The memory only grows. There is no support for releasing an element you take
|
25
|
+
// back to the pool.
|
26
|
+
typedef struct MMDB_data_pool_s {
|
27
|
+
// Index of the current block we're allocating out of.
|
28
|
+
size_t index;
|
29
|
+
|
30
|
+
// The size of the current block, counting by structs.
|
31
|
+
size_t size;
|
32
|
+
|
33
|
+
// How many used in the current block, counting by structs.
|
34
|
+
size_t used;
|
35
|
+
|
36
|
+
// The current block we're allocating out of.
|
37
|
+
MMDB_entry_data_list_s *block;
|
38
|
+
|
39
|
+
// The size of each block.
|
40
|
+
size_t sizes[DATA_POOL_NUM_BLOCKS];
|
41
|
+
|
42
|
+
// An array of pointers to blocks of memory holding space for list
|
43
|
+
// elements.
|
44
|
+
MMDB_entry_data_list_s *blocks[DATA_POOL_NUM_BLOCKS];
|
45
|
+
} MMDB_data_pool_s;
|
46
|
+
|
47
|
+
MMDB_data_pool_s *data_pool_new(size_t const);
|
48
|
+
void data_pool_destroy(MMDB_data_pool_s *const);
|
49
|
+
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const);
|
50
|
+
MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const);
|
51
|
+
|
52
|
+
#endif
|