librtree 0.9.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -0
- data/COPYING +21 -0
- data/README.md +87 -0
- data/ext/rtree/extconf.rb +37 -19
- data/ext/rtree/lib/README.md +9 -0
- data/ext/rtree/lib/bindex.c +157 -0
- data/ext/rtree/lib/bindex.h +31 -0
- data/ext/rtree/lib/bounds.h +21 -0
- data/ext/rtree/lib/branch.c +51 -0
- data/ext/rtree/lib/branches.c +17 -0
- data/ext/rtree/lib/bsrt.c +704 -0
- data/ext/rtree/lib/bsrt.h +16 -0
- data/ext/rtree/lib/constants.h +19 -0
- data/ext/rtree/lib/csv.c +81 -0
- data/ext/rtree/lib/csv.h +16 -0
- data/ext/rtree/lib/endianness.h +83 -0
- data/ext/rtree/lib/error.c +47 -0
- data/ext/rtree/lib/json.c +491 -0
- data/ext/rtree/lib/json.h +16 -0
- data/ext/rtree/lib/mk/Hdr.mk +3 -0
- data/ext/rtree/lib/mk/MakeDepend +25 -0
- data/ext/rtree/lib/mk/Obj.mk +3 -0
- data/ext/rtree/lib/node.c +736 -0
- data/ext/rtree/lib/package.c +11 -0
- data/ext/rtree/lib/page.c +47 -0
- data/ext/rtree/lib/page.h +13 -0
- data/ext/rtree/lib/postscript.c +543 -0
- data/ext/rtree/lib/rect.c +139 -0
- data/ext/rtree/lib/rectf.c +219 -0
- data/ext/rtree/lib/rtree/branch.h +105 -0
- data/ext/rtree/lib/rtree/branches.h +38 -0
- data/ext/rtree/lib/rtree/error.h +42 -0
- data/ext/rtree/lib/rtree/extent.h +20 -0
- data/ext/rtree/lib/rtree/node.h +96 -0
- data/ext/rtree/lib/rtree/package.h +14 -0
- data/ext/rtree/lib/rtree/postscript.h +66 -0
- data/ext/rtree/lib/rtree/rect.h +38 -0
- data/ext/rtree/lib/rtree/rectf.h +34 -0
- data/ext/rtree/lib/rtree/search.h +27 -0
- data/ext/rtree/lib/rtree/state.h +113 -0
- data/ext/rtree/lib/rtree/types.h +14 -0
- data/ext/rtree/lib/rtree-base.c +197 -0
- data/ext/rtree/lib/rtree.h +62 -0
- data/ext/rtree/lib/search.c +54 -0
- data/ext/rtree/lib/split.c +710 -0
- data/ext/rtree/lib/split.h +15 -0
- data/ext/rtree/lib/spvol.c +48 -0
- data/ext/rtree/lib/spvol.h +13 -0
- data/ext/rtree/lib/state.c +169 -0
- data/ext/rtree/rtree.c +11 -0
- data/lib/rtree.rb +4 -4
- metadata +65 -3
@@ -0,0 +1,704 @@
|
|
1
|
+
#ifdef HAVE_CONFIG_H
|
2
|
+
#include "config.h"
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#include "bsrt.h"
|
6
|
+
|
7
|
+
#include "rtree/error.h"
|
8
|
+
#include "rtree/branches.h"
|
9
|
+
|
10
|
+
#include <errno.h>
|
11
|
+
#include <string.h>
|
12
|
+
|
13
|
+
#ifdef WITH_BSRT
|
14
|
+
|
15
|
+
#include "endianness.h"
|
16
|
+
#include "bounds.h"
|
17
|
+
|
18
|
+
#define BSRT_MAGIC "BSRt"
|
19
|
+
#define BSRT_FOOTER "fin"
|
20
|
+
#define BSRT_VERSION 2
|
21
|
+
|
22
|
+
/* magic number, 4 bytes */
|
23
|
+
|
24
|
+
static int write_magic(FILE *stream)
|
25
|
+
{
|
26
|
+
if (fwrite(BSRT_MAGIC, 1, 4, stream) != 4)
|
27
|
+
return RTREE_ERR_FWRITE;
|
28
|
+
|
29
|
+
return RTREE_OK;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* version, 2 bytes */
|
33
|
+
|
34
|
+
static int write_version(FILE *stream)
|
35
|
+
{
|
36
|
+
uint16_t v = htole16(BSRT_VERSION);
|
37
|
+
|
38
|
+
if (fwrite(&v, 2, 1, stream) != 1)
|
39
|
+
return RTREE_ERR_FWRITE;
|
40
|
+
|
41
|
+
return RTREE_OK;
|
42
|
+
}
|
43
|
+
|
44
|
+
/* state, 12 bytes */
|
45
|
+
|
46
|
+
static int write_state(state_t *state, FILE *stream)
|
47
|
+
{
|
48
|
+
uint16_t v[6] =
|
49
|
+
{
|
50
|
+
htole16(state_dims(state)),
|
51
|
+
htole16(state_page_size(state)),
|
52
|
+
htole16(SIZEOF_RTREE_COORD_T),
|
53
|
+
htole16(state_rect_size(state)),
|
54
|
+
htole16(state_branch_size(state)),
|
55
|
+
htole16(state_node_size(state))
|
56
|
+
};
|
57
|
+
|
58
|
+
if (fwrite(&v, 2, 6, stream) != 6)
|
59
|
+
return RTREE_ERR_FWRITE;
|
60
|
+
|
61
|
+
return RTREE_OK;
|
62
|
+
}
|
63
|
+
|
64
|
+
/*
|
65
|
+
each node has a 4-byte header, the level (positive for an internal
|
66
|
+
node, zero for a leaf node) and the count of branches.
|
67
|
+
*/
|
68
|
+
|
69
|
+
static int write_header(uint16_t level, uint16_t count, FILE *stream)
|
70
|
+
{
|
71
|
+
uint16_t v;
|
72
|
+
|
73
|
+
v = htole16(level);
|
74
|
+
|
75
|
+
if (fwrite(&v, 2, 1, stream) != 1)
|
76
|
+
return RTREE_ERR_FWRITE;
|
77
|
+
|
78
|
+
v = htole16(count);
|
79
|
+
|
80
|
+
if (fwrite(&v, 2, 1, stream) != 1)
|
81
|
+
return RTREE_ERR_FWRITE;
|
82
|
+
|
83
|
+
return RTREE_OK;
|
84
|
+
}
|
85
|
+
|
86
|
+
static int write_id(rtree_id_t id, FILE *stream)
|
87
|
+
{
|
88
|
+
#if SIZEOF_RTREE_ID_T == 2
|
89
|
+
uint16_t v = htole16(id);
|
90
|
+
#elif SIZEOF_RTREE_ID_T == 4
|
91
|
+
uint32_t v = htole32(id);
|
92
|
+
#elif SIZEOF_RTREE_ID_T == 8
|
93
|
+
uint64_t v = htole64(id);
|
94
|
+
#else
|
95
|
+
#error rtree_id_t size not handled
|
96
|
+
#endif
|
97
|
+
|
98
|
+
if (fwrite(&v, SIZEOF_RTREE_ID_T, 1, stream) != 1)
|
99
|
+
return RTREE_ERR_FWRITE;
|
100
|
+
|
101
|
+
return RTREE_OK;
|
102
|
+
}
|
103
|
+
|
104
|
+
/*
|
105
|
+
Here we only byte-swap if we establish that the host float
|
106
|
+
byte-order is big-endian, this saves time on little-endian
|
107
|
+
hardware. Note that in the big-endian case, we call htole32()
|
108
|
+
which converts from the host integer byte-order to little-endian,
|
109
|
+
this will only be correct if integer and float endianess are
|
110
|
+
the same, this is not true in general (!), there exists real
|
111
|
+
hardware with big-endian floats and little-endian integers.
|
112
|
+
So it would be better to use be32tole32() here, but that does
|
113
|
+
not exist (one could make it with htole32(be32toh()), but
|
114
|
+
these are macros not functions, one would need to test this on
|
115
|
+
real hardware first).
|
116
|
+
*/
|
117
|
+
|
118
|
+
static int write_rect(const state_t *state,
|
119
|
+
const rtree_coord_t *rect,
|
120
|
+
FILE *stream)
|
121
|
+
{
|
122
|
+
size_t
|
123
|
+
n = 2 * state_dims(state),
|
124
|
+
k = SIZEOF_RTREE_COORD_T;
|
125
|
+
|
126
|
+
#ifdef FLOAT_WORDS_BIGENDIAN
|
127
|
+
|
128
|
+
rtree_coord_t buffer[n];
|
129
|
+
|
130
|
+
for (size_t i = 0 ; i < n ; i++)
|
131
|
+
{
|
132
|
+
/*
|
133
|
+
The type-punning to/from char* here is legal (the standard
|
134
|
+
makes an explicit exception), but cppcheck warns anyway, so
|
135
|
+
we suppress those warnings
|
136
|
+
*/
|
137
|
+
|
138
|
+
char p[k];
|
139
|
+
|
140
|
+
/* cppcheck-suppress invalidPointerCast */
|
141
|
+
*(rtree_coord_t*)p = rect[i];
|
142
|
+
|
143
|
+
#if SIZEOF_RTREE_COORD_T == 4
|
144
|
+
/* cppcheck-suppress invalidPointerCast */
|
145
|
+
*(uint32_t*)p = htole32(*(uint32_t*)p);
|
146
|
+
#elif SIZEOF_RTREE_COORD_T == 8
|
147
|
+
/* cppcheck-suppress invalidPointerCast */
|
148
|
+
*(uint64_t*)p = htole64(*(uint64_t*)p);
|
149
|
+
#else
|
150
|
+
#error rtree_coord_t size not handled
|
151
|
+
#endif
|
152
|
+
|
153
|
+
/* cppcheck-suppress invalidPointerCast */
|
154
|
+
buffer[i] = *(rtree_coord_t*)p;
|
155
|
+
}
|
156
|
+
|
157
|
+
if (fwrite(buffer, k, n, stream) != n)
|
158
|
+
return RTREE_ERR_FWRITE;
|
159
|
+
return RTREE_OK;
|
160
|
+
|
161
|
+
#else
|
162
|
+
|
163
|
+
if (fwrite(rect, k, n, stream) != n)
|
164
|
+
return RTREE_ERR_FWRITE;
|
165
|
+
return RTREE_OK;
|
166
|
+
|
167
|
+
#endif
|
168
|
+
}
|
169
|
+
|
170
|
+
static int write_node(const state_t*, const node_t*, FILE*);
|
171
|
+
|
172
|
+
/* callbacks passed to node_branch_each() */
|
173
|
+
|
174
|
+
static int write_internal_branch(const state_t *state,
|
175
|
+
const branch_t *branch,
|
176
|
+
void *arg)
|
177
|
+
{
|
178
|
+
FILE *stream = arg;
|
179
|
+
int err;
|
180
|
+
|
181
|
+
if ((err = write_rect(state, branch->rect, stream)) != 0)
|
182
|
+
return err;
|
183
|
+
|
184
|
+
const node_t *child = branch_get_child(branch);
|
185
|
+
|
186
|
+
if ((err = write_node(state, child, stream)) != 0)
|
187
|
+
return err;
|
188
|
+
|
189
|
+
return 0;
|
190
|
+
}
|
191
|
+
|
192
|
+
static int write_leaf_branch(const state_t *state,
|
193
|
+
const branch_t *branch,
|
194
|
+
void *arg)
|
195
|
+
{
|
196
|
+
FILE *stream = arg;
|
197
|
+
int err;
|
198
|
+
|
199
|
+
if ((err = write_rect(state, branch->rect, stream)) != 0)
|
200
|
+
return err;
|
201
|
+
|
202
|
+
rtree_id_t id = branch_get_id(branch);
|
203
|
+
|
204
|
+
if ((err = write_id(id, stream)) != 0)
|
205
|
+
return err;
|
206
|
+
|
207
|
+
return 0;
|
208
|
+
}
|
209
|
+
|
210
|
+
/* write internal/leaf nodes */
|
211
|
+
|
212
|
+
static int write_internal_node(const state_t *state,
|
213
|
+
const node_t *node,
|
214
|
+
FILE *stream)
|
215
|
+
{
|
216
|
+
int err;
|
217
|
+
|
218
|
+
if ((err = write_header(node_level(node), node_count(node), stream)) != 0)
|
219
|
+
return err;
|
220
|
+
|
221
|
+
return node_branch_each(state, node, write_internal_branch, stream);
|
222
|
+
}
|
223
|
+
|
224
|
+
static int write_leaf_node(const state_t *state,
|
225
|
+
const node_t *node,
|
226
|
+
FILE *stream)
|
227
|
+
{
|
228
|
+
int err;
|
229
|
+
|
230
|
+
if ((err = write_header(node_level(node), node_count(node), stream)) != 0)
|
231
|
+
return err;
|
232
|
+
|
233
|
+
return node_branch_each(state, node, write_leaf_branch, stream);
|
234
|
+
}
|
235
|
+
|
236
|
+
static int write_node(const state_t *state,
|
237
|
+
const node_t *node,
|
238
|
+
FILE *stream)
|
239
|
+
{
|
240
|
+
int err;
|
241
|
+
|
242
|
+
if (node_level(node) > 0)
|
243
|
+
err = write_internal_node(state, node, stream);
|
244
|
+
else
|
245
|
+
err = write_leaf_node(state, node, stream);
|
246
|
+
|
247
|
+
return err;
|
248
|
+
}
|
249
|
+
|
250
|
+
static int write_footer(FILE *stream)
|
251
|
+
{
|
252
|
+
size_t n = strlen(BSRT_FOOTER);
|
253
|
+
if (fwrite(BSRT_FOOTER, 1, n, stream) != n)
|
254
|
+
return RTREE_ERR_FWRITE;
|
255
|
+
return RTREE_OK;
|
256
|
+
}
|
257
|
+
|
258
|
+
int bsrt_rtree_write(const rtree_t *rtree, FILE *stream)
|
259
|
+
{
|
260
|
+
int err;
|
261
|
+
|
262
|
+
if ((err = write_magic(stream)) != 0)
|
263
|
+
return err;
|
264
|
+
|
265
|
+
if ((err = write_version(stream)) != 0)
|
266
|
+
return err;
|
267
|
+
|
268
|
+
if ((err = write_state(rtree->state, stream)) != 0)
|
269
|
+
return err;
|
270
|
+
|
271
|
+
if ((err = write_node(rtree->state, rtree->root, stream)) != 0)
|
272
|
+
return err;
|
273
|
+
|
274
|
+
if ((err = write_footer(stream)) != 0)
|
275
|
+
return err;
|
276
|
+
|
277
|
+
return RTREE_OK;
|
278
|
+
}
|
279
|
+
|
280
|
+
/*
|
281
|
+
reader functions, unlike the writer, all functions acting on
|
282
|
+
file content after the version are version qualified, the idea
|
283
|
+
being that later versions of the library should be able to
|
284
|
+
read all previous versions of the format.
|
285
|
+
*/
|
286
|
+
|
287
|
+
static int read_magic(FILE *stream)
|
288
|
+
{
|
289
|
+
char buffer[4];
|
290
|
+
|
291
|
+
if (fread(buffer, 1, 4, stream) != 4)
|
292
|
+
return 1;
|
293
|
+
|
294
|
+
if (memcmp(buffer, BSRT_MAGIC, 4) == 0)
|
295
|
+
return 0;
|
296
|
+
|
297
|
+
errno = EINVAL;
|
298
|
+
return 1;
|
299
|
+
}
|
300
|
+
|
301
|
+
static int read_version(FILE *stream, uint16_t *v)
|
302
|
+
{
|
303
|
+
if (fread(v, 2, 1, stream) != 1)
|
304
|
+
return 1;
|
305
|
+
|
306
|
+
*v = le16toh(*v);
|
307
|
+
|
308
|
+
return 0;
|
309
|
+
}
|
310
|
+
|
311
|
+
/* read v1 */
|
312
|
+
|
313
|
+
static int read_v1_header(FILE *stream, uint16_t v[5])
|
314
|
+
{
|
315
|
+
if (fread(v, 2, 5, stream) != 5)
|
316
|
+
return 1;
|
317
|
+
|
318
|
+
for (size_t i = 0 ; i < 5 ; i++)
|
319
|
+
v[i] = le16toh(v[i]);
|
320
|
+
|
321
|
+
return 0;
|
322
|
+
}
|
323
|
+
|
324
|
+
static bool read_v1_state_consistent(uint16_t v[5], const state_t *state)
|
325
|
+
{
|
326
|
+
return
|
327
|
+
(v[0] == state_dims(state)) &&
|
328
|
+
(v[1] == state_page_size(state)) &&
|
329
|
+
(v[2] == SIZEOF_RTREE_COORD_T) &&
|
330
|
+
(v[3] == state_rect_size(state)) &&
|
331
|
+
(v[4] == state_branch_size(state));
|
332
|
+
}
|
333
|
+
|
334
|
+
/* see note above on float/double endianness */
|
335
|
+
|
336
|
+
static int read_v1_rect(FILE *stream,
|
337
|
+
const state_t *state,
|
338
|
+
rtree_coord_t *rect)
|
339
|
+
{
|
340
|
+
size_t
|
341
|
+
n = 2 * state_dims(state),
|
342
|
+
k = SIZEOF_RTREE_COORD_T;
|
343
|
+
|
344
|
+
#ifdef FLOAT_WORDS_BIGENDIAN
|
345
|
+
|
346
|
+
char buffer[n * k];
|
347
|
+
|
348
|
+
if (fread(buffer, k, n, stream) != n)
|
349
|
+
return 1;
|
350
|
+
|
351
|
+
for (size_t i = 0 ; i < n ; i++)
|
352
|
+
{
|
353
|
+
char *p = buffer + i * k;
|
354
|
+
|
355
|
+
#if SIZEOF_RTREE_COORD_T == 4
|
356
|
+
*(uint32_t*)p = le32toh(*(uint32_t*)p);
|
357
|
+
#elif SIZEOF_RTREE_COORD_T == 8
|
358
|
+
*(uint64_t*)p = le64toh(*(uint64_t*)p);
|
359
|
+
#else
|
360
|
+
#error rtree_coord_t size not handled
|
361
|
+
#endif
|
362
|
+
|
363
|
+
/* cppcheck-suppress invalidPointerCast */
|
364
|
+
|
365
|
+
rect[i] = *(rtree_coord_t*)p;
|
366
|
+
}
|
367
|
+
|
368
|
+
#else
|
369
|
+
|
370
|
+
if (fread(rect, k, n, stream) != n)
|
371
|
+
return 1;
|
372
|
+
|
373
|
+
#endif
|
374
|
+
|
375
|
+
return 0;
|
376
|
+
}
|
377
|
+
|
378
|
+
static int read_v1_id(FILE *stream, rtree_id_t *id)
|
379
|
+
{
|
380
|
+
if (fread(id, SIZEOF_RTREE_ID_T, 1, stream) != 1)
|
381
|
+
return 1;
|
382
|
+
|
383
|
+
#if SIZEOF_RTREE_ID_T == 8
|
384
|
+
*id = le64toh(*id);
|
385
|
+
#elif SIZEOF_RTREE_ID_T == 4
|
386
|
+
*id = le32toh(*id);
|
387
|
+
#elif SIZEOF_RTREE_ID_T == 2
|
388
|
+
*id = le16toh(*id);
|
389
|
+
#else
|
390
|
+
#error rtree_id_t size not handled
|
391
|
+
#endif
|
392
|
+
|
393
|
+
return 0;
|
394
|
+
}
|
395
|
+
|
396
|
+
static node_t* read_v1_node(FILE*, const state_t*);
|
397
|
+
|
398
|
+
static int read_v1_branch_internal(FILE *stream,
|
399
|
+
const state_t *state,
|
400
|
+
branch_t *branch)
|
401
|
+
{
|
402
|
+
if (branch_init(state, branch) != 0)
|
403
|
+
return 1;
|
404
|
+
|
405
|
+
if (read_v1_rect(stream, state, branch_get_rect_mutable(branch)) != 0)
|
406
|
+
return 1;
|
407
|
+
|
408
|
+
node_t *child;
|
409
|
+
|
410
|
+
if ((child = read_v1_node(stream, state)) == NULL)
|
411
|
+
return 1;
|
412
|
+
|
413
|
+
branch_set_child(branch, child);
|
414
|
+
|
415
|
+
return 0;
|
416
|
+
}
|
417
|
+
|
418
|
+
static int read_v1_branch_leaf(FILE *stream,
|
419
|
+
const state_t *state,
|
420
|
+
branch_t *branch)
|
421
|
+
{
|
422
|
+
if (branch_init(state, branch) != 0)
|
423
|
+
return 1;
|
424
|
+
|
425
|
+
if (read_v1_rect(stream, state, branch_get_rect_mutable(branch)) != 0)
|
426
|
+
return 1;
|
427
|
+
|
428
|
+
rtree_id_t id;
|
429
|
+
|
430
|
+
if (read_v1_id(stream, &id) != 0)
|
431
|
+
return 1;
|
432
|
+
|
433
|
+
branch_set_id(branch, id);
|
434
|
+
|
435
|
+
return 0;
|
436
|
+
}
|
437
|
+
|
438
|
+
typedef int (branch_read_t)(FILE*, const state_t*, branch_t*);
|
439
|
+
|
440
|
+
static node_t* read_v1_node_generic(FILE *stream,
|
441
|
+
branch_read_t *f,
|
442
|
+
const state_t *state,
|
443
|
+
uint16_t n)
|
444
|
+
{
|
445
|
+
if (n > state_branching_factor(state))
|
446
|
+
{
|
447
|
+
errno = EINVAL;
|
448
|
+
return NULL;
|
449
|
+
}
|
450
|
+
|
451
|
+
node_t *node;
|
452
|
+
|
453
|
+
if ((node = node_new(state)) != NULL)
|
454
|
+
{
|
455
|
+
void *branches = node_get_branches(node);
|
456
|
+
|
457
|
+
for (size_t i = 0 ; i < n ; i++)
|
458
|
+
{
|
459
|
+
branch_t *branch = branches_get(state, branches, i);
|
460
|
+
if (f(stream, state, branch) != 0)
|
461
|
+
break;
|
462
|
+
node_count_increment(node);
|
463
|
+
}
|
464
|
+
|
465
|
+
if (node_count(node) == n)
|
466
|
+
return node;
|
467
|
+
|
468
|
+
errno = EINVAL;
|
469
|
+
node_destroy(state, node);
|
470
|
+
}
|
471
|
+
|
472
|
+
return NULL;
|
473
|
+
}
|
474
|
+
|
475
|
+
static node_t* read_v1_node_internal(FILE *stream,
|
476
|
+
const state_t *state,
|
477
|
+
uint16_t n)
|
478
|
+
{
|
479
|
+
return read_v1_node_generic(stream, read_v1_branch_internal, state, n);
|
480
|
+
}
|
481
|
+
|
482
|
+
static node_t* read_v1_node_leaf(FILE *stream,
|
483
|
+
const state_t *state,
|
484
|
+
uint16_t n)
|
485
|
+
{
|
486
|
+
return read_v1_node_generic(stream, read_v1_branch_leaf, state, n);
|
487
|
+
}
|
488
|
+
|
489
|
+
static node_t* read_v1_node(FILE *stream, const state_t *state)
|
490
|
+
{
|
491
|
+
uint16_t level;
|
492
|
+
|
493
|
+
if (fread(&level, 2, 1, stream) != 1)
|
494
|
+
return NULL;
|
495
|
+
level = le16toh(level);
|
496
|
+
if (level > RTREE_LEVELS_MAX)
|
497
|
+
return NULL;
|
498
|
+
|
499
|
+
uint16_t count;
|
500
|
+
|
501
|
+
if (fread(&count, 2, 1, stream) != 1)
|
502
|
+
return NULL;
|
503
|
+
count = le16toh(count);
|
504
|
+
if (count > RTREE_BRANCHES_MAX)
|
505
|
+
return NULL;
|
506
|
+
|
507
|
+
node_t *node;
|
508
|
+
|
509
|
+
if (level > 0)
|
510
|
+
node = read_v1_node_internal(stream, state, count);
|
511
|
+
else
|
512
|
+
node = read_v1_node_leaf(stream, state, count);
|
513
|
+
|
514
|
+
if (node != NULL)
|
515
|
+
node_set_level(node, level);
|
516
|
+
|
517
|
+
return node;
|
518
|
+
}
|
519
|
+
|
520
|
+
static int read_v1_footer(FILE *stream)
|
521
|
+
{
|
522
|
+
size_t n = strlen(BSRT_FOOTER);
|
523
|
+
char buffer[n];
|
524
|
+
|
525
|
+
if (fread(buffer, 1, n, stream) != n)
|
526
|
+
return 1;
|
527
|
+
|
528
|
+
if (memcmp(buffer, BSRT_FOOTER, n) == 0)
|
529
|
+
return 0;
|
530
|
+
else
|
531
|
+
{
|
532
|
+
errno = EINVAL;
|
533
|
+
return 1;
|
534
|
+
}
|
535
|
+
}
|
536
|
+
|
537
|
+
static rtree_t* read_v1(FILE *stream)
|
538
|
+
{
|
539
|
+
uint16_t v[5];
|
540
|
+
|
541
|
+
if (read_v1_header(stream, v) != 0)
|
542
|
+
return NULL;
|
543
|
+
|
544
|
+
size_t dims = v[0];
|
545
|
+
|
546
|
+
if (dims > RTREE_DIMS_MAX)
|
547
|
+
return NULL;
|
548
|
+
|
549
|
+
state_t *state;
|
550
|
+
|
551
|
+
if ((state = state_new(dims, RTREE_NODE_PAGE(1))) != NULL)
|
552
|
+
{
|
553
|
+
if (read_v1_state_consistent(v, state))
|
554
|
+
{
|
555
|
+
node_t *root;
|
556
|
+
|
557
|
+
if ((root = read_v1_node(stream, state)) != NULL)
|
558
|
+
{
|
559
|
+
if (read_v1_footer(stream) == 0)
|
560
|
+
{
|
561
|
+
rtree_t *rtree;
|
562
|
+
|
563
|
+
if ((rtree = rtree_alloc()) != NULL)
|
564
|
+
{
|
565
|
+
rtree->state = state;
|
566
|
+
rtree->root = root;
|
567
|
+
return rtree;
|
568
|
+
}
|
569
|
+
}
|
570
|
+
node_destroy(state, root);
|
571
|
+
}
|
572
|
+
}
|
573
|
+
else
|
574
|
+
errno = EINVAL;
|
575
|
+
|
576
|
+
state_destroy(state);
|
577
|
+
}
|
578
|
+
|
579
|
+
return NULL;
|
580
|
+
}
|
581
|
+
|
582
|
+
/* read v2 */
|
583
|
+
|
584
|
+
static int read_v2_header(FILE *stream, uint16_t v[6])
|
585
|
+
{
|
586
|
+
if (fread(v, 2, 6, stream) != 6)
|
587
|
+
return 1;
|
588
|
+
|
589
|
+
for (size_t i = 0 ; i < 6 ; i++)
|
590
|
+
v[i] = le16toh(v[i]);
|
591
|
+
|
592
|
+
return 0;
|
593
|
+
}
|
594
|
+
|
595
|
+
static bool read_v2_state_consistent(uint16_t v[6], const state_t *state)
|
596
|
+
{
|
597
|
+
return
|
598
|
+
(v[0] == state_dims(state)) &&
|
599
|
+
(v[1] == state_page_size(state)) &&
|
600
|
+
(v[2] == SIZEOF_RTREE_COORD_T) &&
|
601
|
+
(v[3] == state_rect_size(state)) &&
|
602
|
+
(v[4] == state_branch_size(state)) &&
|
603
|
+
(v[5] == state_node_size(state));
|
604
|
+
}
|
605
|
+
|
606
|
+
static node_t* read_v2_node(FILE *stream, const state_t *state)
|
607
|
+
{
|
608
|
+
return read_v1_node(stream, state);
|
609
|
+
}
|
610
|
+
|
611
|
+
static int read_v2_footer(FILE *stream)
|
612
|
+
{
|
613
|
+
return read_v1_footer(stream);
|
614
|
+
}
|
615
|
+
|
616
|
+
static rtree_t* read_v2(FILE *stream)
|
617
|
+
{
|
618
|
+
uint16_t v[6];
|
619
|
+
|
620
|
+
if (read_v2_header(stream, v) != 0)
|
621
|
+
return NULL;
|
622
|
+
|
623
|
+
if ((v[5] == 0) || (v[1] < v[5]))
|
624
|
+
return NULL;
|
625
|
+
|
626
|
+
size_t
|
627
|
+
dims = v[0],
|
628
|
+
node_page = v[1] / v[5];
|
629
|
+
state_t *state;
|
630
|
+
|
631
|
+
if ((state = state_new(dims, RTREE_NODE_PAGE(node_page))) != NULL)
|
632
|
+
{
|
633
|
+
if (read_v2_state_consistent(v, state))
|
634
|
+
{
|
635
|
+
node_t *root;
|
636
|
+
|
637
|
+
if ((root = read_v2_node(stream, state)) != NULL)
|
638
|
+
{
|
639
|
+
if (read_v2_footer(stream) == 0)
|
640
|
+
{
|
641
|
+
rtree_t *rtree;
|
642
|
+
|
643
|
+
if ((rtree = rtree_alloc()) != NULL)
|
644
|
+
{
|
645
|
+
rtree->state = state;
|
646
|
+
rtree->root = root;
|
647
|
+
return rtree;
|
648
|
+
}
|
649
|
+
}
|
650
|
+
node_destroy(state, root);
|
651
|
+
}
|
652
|
+
}
|
653
|
+
else
|
654
|
+
errno = EINVAL;
|
655
|
+
|
656
|
+
state_destroy(state);
|
657
|
+
}
|
658
|
+
|
659
|
+
return NULL;
|
660
|
+
}
|
661
|
+
|
662
|
+
rtree_t* bsrt_rtree_read(FILE *stream)
|
663
|
+
{
|
664
|
+
if (read_magic(stream) != 0)
|
665
|
+
return NULL;
|
666
|
+
|
667
|
+
uint16_t version;
|
668
|
+
|
669
|
+
if (read_version(stream, &version) != 0)
|
670
|
+
return NULL;
|
671
|
+
|
672
|
+
switch (version)
|
673
|
+
{
|
674
|
+
case 1:
|
675
|
+
return read_v1(stream);
|
676
|
+
case 2:
|
677
|
+
return read_v2(stream);
|
678
|
+
default:
|
679
|
+
errno = EINVAL;
|
680
|
+
return NULL;
|
681
|
+
}
|
682
|
+
}
|
683
|
+
|
684
|
+
#else
|
685
|
+
|
686
|
+
#pragma GCC diagnostic push
|
687
|
+
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
688
|
+
int bsrt_rtree_write(const rtree_t *rtree, FILE *stream)
|
689
|
+
{
|
690
|
+
errno = ENOSYS;
|
691
|
+
return RTREE_ERR_NOBSRT;
|
692
|
+
}
|
693
|
+
#pragma GCC diagnostic pop
|
694
|
+
|
695
|
+
#pragma GCC diagnostic push
|
696
|
+
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
697
|
+
rtree_t* bsrt_rtree_read(FILE *stream)
|
698
|
+
{
|
699
|
+
errno = ENOSYS;
|
700
|
+
return NULL;
|
701
|
+
}
|
702
|
+
#pragma GCC diagnostic pop
|
703
|
+
|
704
|
+
#endif
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
constants.h
|
3
|
+
Copyright (c) J.J. Green 2019
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef CONSTANTS_H
|
7
|
+
#define CONSTANTS_H
|
8
|
+
|
9
|
+
#include <math.h>
|
10
|
+
|
11
|
+
#ifndef M_PI
|
12
|
+
#define M_PI 3.14159265358979323846
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#ifndef M_LOG_PI
|
16
|
+
#define M_LOG_PI 1.1447298858494002
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#endif
|