source: trunk/src/stringpool.h @ 3923

Last change on this file since 3923 was 267, checked in by ksherdy, 10 years ago

Construct and pass string literals as read only (const char *) types.

File size: 4.4 KB
Line 
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
5    Free License 3.0.
6
7    A storage pool for strings all of which remain allocated
8    until the pool is destroyed.
9*/
10#ifndef STRINGPOOL_H
11#define STRINGPOOL_H
12
13template <int BasePoolSize, int ExpansionPercent>
14class StringPool {
15public:
16        StringPool();
17        ~StringPool();
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(). */
22        void OpenString();
23        void AppendSegment(char * segment, int segment_lgth);
24        char * CloseString();  /* Return the pointer to the constructed string. */
25private:
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. */
30        struct buffer_node {
31                buffer_node * more_buffers;
32                size_t buffer_size;
33                char buffer[BasePoolSize];
34        };
35        buffer_node node1;
36        buffer_node * current_node;
37        size_t total_size;
38        char * insertion_ptr;
39        size_t space_avail;
40        char * opened_string_ptr;
41
42        void ExtendPool();  /* Adds a new buffer to the pool. */
43};
44
45template <int BasePoolSize, int ExpansionPercent>
46StringPool<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;
54}
55
56template <int BasePoolSize, int ExpansionPercent>
57StringPool<BasePoolSize, ExpansionPercent>::~StringPool() {
58        while (current_node != &node1) {
59                buffer_node * allocated_node = current_node;
60                current_node = allocated_node->more_buffers;
61                free(allocated_node);
62        }
63}
64
65template <int BasePoolSize, int ExpansionPercent>
66void 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");
71                exit(-1);
72        }
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;
83        }
84        else {
85                insertion_ptr = new_node->buffer;
86                space_avail = new_buffer_size;
87        }
88#ifdef DEBUG
89        printf("ExtendPool() called: space_avail = %i\n", space_avail);
90#endif
91}
92
93template <int BasePoolSize, int ExpansionPercent>
94char * 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;
102#ifdef DEBUG
103        printf("Insert(%s, %i)\n", this_string_ptr, lgth);
104#endif
105        return this_string_ptr;
106}
107
108template <int BasePoolSize, int ExpansionPercent>
109void StringPool<BasePoolSize, ExpansionPercent>::OpenString() {
110        opened_string_ptr = insertion_ptr;
111}
112
113template <int BasePoolSize, int ExpansionPercent>
114void 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;
120}
121
122template <int BasePoolSize, int ExpansionPercent>
123char * StringPool<BasePoolSize, ExpansionPercent>::CloseString() {
124        insertion_ptr[0] = '\0';
125        insertion_ptr++;
126        space_avail--;
127        char * this_string_ptr = opened_string_ptr;
128        opened_string_ptr = NULL;
129        return this_string_ptr;
130}
131#endif
Note: See TracBrowser for help on using the repository browser.