1
/* stringpool.h - Coterminal String Pools.
2
Copyright (c) 2008, Robert D. Cameron.
3
Licensed to the public under the Open Software License 3.0.
4
Licensed to International Characters, Inc., under the Academic
7
A storage pool for strings all of which remain allocated
8
until the pool is destroyed.
13
template <int BasePoolSize, int ExpansionPercent>
18
char * Insert(const char * full_string, int lgth);
19
/* The following methods provide for incremental construction of strings
20
each constructed by a sequence of calls of the form:
21
OpenString(); AppendSegment(...)+; CloseString(). */
23
void AppendSegment(char * segment, int segment_lgth);
24
char * CloseString(); /* Return the pointer to the constructed string. */
26
/* The initial buffer is allocated as part of the StringPool object.
27
For stack allocated StringPools that do not exceed the initial
28
BasePoolSize, this completely eliminates the overhead and memory
29
fragmentation associated with calls to new and delete. */
31
buffer_node * more_buffers;
33
char buffer[BasePoolSize];
36
buffer_node * current_node;
40
char * opened_string_ptr;
42
void ExtendPool(); /* Adds a new buffer to the pool. */
45
template <int BasePoolSize, int ExpansionPercent>
46
StringPool<BasePoolSize, ExpansionPercent>::StringPool() {
47
node1.more_buffers = NULL;
48
node1.buffer_size = BasePoolSize;
49
total_size = node1.buffer_size;
50
insertion_ptr = (char *) &(node1.buffer);
51
space_avail = node1.buffer_size;
52
opened_string_ptr = NULL; /* not open */
53
current_node = &node1;
56
template <int BasePoolSize, int ExpansionPercent>
57
StringPool<BasePoolSize, ExpansionPercent>::~StringPool() {
58
while (current_node != &node1) {
59
buffer_node * allocated_node = current_node;
60
current_node = allocated_node->more_buffers;
65
template <int BasePoolSize, int ExpansionPercent>
66
void StringPool<BasePoolSize, ExpansionPercent>::ExtendPool() {
67
size_t new_buffer_size = (size_t) ((total_size * ExpansionPercent)/100);
68
buffer_node * new_node = (buffer_node *) malloc(sizeof(buffer_node) + new_buffer_size - BasePoolSize);
69
if (new_node == NULL) {
70
fprintf(stderr, "Allocation failure in StringPool<BasePoolSize, ExpansionPercent>::ExtendPool\n");
73
new_node->more_buffers = current_node;
74
new_node->buffer_size = new_buffer_size;
75
total_size += new_buffer_size;
76
current_node = new_node;
77
if (opened_string_ptr != NULL) {
78
size_t open_string_prefix_size = (size_t) insertion_ptr - (size_t) opened_string_ptr;
79
memcpy(new_node->buffer, opened_string_ptr, open_string_prefix_size);
80
insertion_ptr = &(new_node->buffer[open_string_prefix_size]);
81
opened_string_ptr = new_node->buffer;
82
space_avail = new_buffer_size - open_string_prefix_size;
85
insertion_ptr = new_node->buffer;
86
space_avail = new_buffer_size;
89
printf("ExtendPool() called: space_avail = %i\n", space_avail);
93
template <int BasePoolSize, int ExpansionPercent>
94
char * StringPool<BasePoolSize, ExpansionPercent>::Insert(const char * s, int lgth) {
95
int total_lgth = lgth + 1;
96
while (total_lgth > space_avail) ExtendPool();
97
memcpy(insertion_ptr, s, lgth);
98
char * this_string_ptr = insertion_ptr;
99
insertion_ptr[lgth] = '\0';
100
insertion_ptr += total_lgth;
101
space_avail -= total_lgth;
103
printf("Insert(%s, %i)\n", this_string_ptr, lgth);
105
return this_string_ptr;
108
template <int BasePoolSize, int ExpansionPercent>
109
void StringPool<BasePoolSize, ExpansionPercent>::OpenString() {
110
opened_string_ptr = insertion_ptr;
113
template <int BasePoolSize, int ExpansionPercent>
114
void StringPool<BasePoolSize, ExpansionPercent>::AppendSegment(char * segment, int segment_lgth) {
115
/* Make sure that there is length for this segment plus null byte. */
116
while (segment_lgth + 1 > space_avail) ExtendPool();
117
memcpy(insertion_ptr, segment, segment_lgth);
118
insertion_ptr += segment_lgth;
119
space_avail -= segment_lgth;
122
template <int BasePoolSize, int ExpansionPercent>
123
char * StringPool<BasePoolSize, ExpansionPercent>::CloseString() {
124
insertion_ptr[0] = '\0';
127
char * this_string_ptr = opened_string_ptr;
128
opened_string_ptr = NULL;
129
return this_string_ptr;