source: trunk/src/stringpool.h @ 4138

Last change on this file since 4138 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
RevLine 
[184]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
[267]13template <int BasePoolSize, int ExpansionPercent>
[184]14class StringPool {
15public:
16        StringPool();
17        ~StringPool();
[267]18        char * Insert(const char * full_string, int lgth);
[184]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:
[267]26        /* The initial buffer is allocated as part of the StringPool object.
[184]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
[267]45template <int BasePoolSize, int ExpansionPercent>
[184]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
[267]56template <int BasePoolSize, int ExpansionPercent>
[184]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
[267]65template <int BasePoolSize, int ExpansionPercent>
[184]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
[267]91}
[184]92
[267]93template <int BasePoolSize, int ExpansionPercent>
94char * StringPool<BasePoolSize, ExpansionPercent>::Insert(const char * s, int lgth) {
[184]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
[267]108template <int BasePoolSize, int ExpansionPercent>
[184]109void StringPool<BasePoolSize, ExpansionPercent>::OpenString() {
110        opened_string_ptr = insertion_ptr;
111}
112
[267]113template <int BasePoolSize, int ExpansionPercent>
[184]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
[267]122template <int BasePoolSize, int ExpansionPercent>
[184]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.