File: strpool.c

package info (click to toggle)
libsfdo 0.1.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 736 kB
  • sloc: ansic: 6,491; python: 111; makefile: 4
file content (82 lines) | stat: -rw-r--r-- 2,005 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "common/strpool.h"

struct sfdo_strpool_chunk {
	struct sfdo_strpool_chunk *next;
	char data[];
};

#define CHUNK_MIN_SIZE (4096 - sizeof(struct sfdo_strpool_chunk) - 8)

const char *sfdo_strpool_add(struct sfdo_strpool *pool, const char *data, size_t len) {
	if (len == 0) {
		return "";
	}

	size_t size = len + 1;
	char *out = NULL;
	if (size > pool->n_free) {
		size_t data_size = size > CHUNK_MIN_SIZE ? size : CHUNK_MIN_SIZE;

		struct sfdo_strpool_chunk *chunk = malloc(sizeof(*chunk) + data_size);
		if (chunk == NULL) {
			return NULL;
		}

		size_t chunk_nfree = data_size - size;
		if (chunk_nfree < pool->n_free) {
			// Put the new chunk after head
			assert(pool->chunks != NULL);
			chunk->next = pool->chunks->next;
			pool->chunks->next = chunk;
		} else {
			// The new chunk is the new head
			chunk->next = pool->chunks;
			pool->chunks = chunk;
			pool->n_free = chunk_nfree;
		}

		out = chunk->data;
	} else {
		// If there's free space, the total size is CHUNK_MIN_SIZE
		char *start = pool->chunks->data + CHUNK_MIN_SIZE - pool->n_free;
		pool->n_free -= size;
		out = start;
	}
	memcpy(out, data, len);
	out[len] = '\0';
	return out;
}

void sfdo_strpool_init(struct sfdo_strpool *pool) {
	pool->chunks = NULL;
	pool->n_free = 0;
}

void sfdo_strpool_finish(struct sfdo_strpool *pool) {
	struct sfdo_strpool_chunk *chunk = pool->chunks;
	while (chunk != NULL) {
		struct sfdo_strpool_chunk *next = chunk->next;
		free(chunk);
		chunk = next;
	}
}

void sfdo_strpool_save(struct sfdo_strpool *pool, struct sfdo_strpool_state *state) {
	state->chunk = pool->chunks;
	state->n_free = pool->n_free;
}

void sfdo_strpool_restore(struct sfdo_strpool *pool, struct sfdo_strpool_state *state) {
	struct sfdo_strpool_chunk *chunk = pool->chunks;
	while (chunk != state->chunk) {
		struct sfdo_strpool_chunk *next = chunk->next;
		free(chunk);
		chunk = next;
	}
	pool->chunks = chunk;
	pool->n_free = state->n_free;
}