source: trunk/symtab/stringpool.h

Last change on this file was 1229, checked in by vla24, 8 years ago

Reorganized SymbolTable? library

File size: 5.0 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
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16
17
18template <int BasePoolSize, int ExpansionPercent>
19class StringPool {
20public:
21        StringPool();
22        ~StringPool();
23        char * Insert(const char * full_string, int lgth);
24        char * Insert(const char * full_string, int lgth, int advance_bit);
25        /* The following methods provide for incremental construction of strings
26           each constructed by a sequence of calls of the form:
27           OpenString(); AppendSegment(...)+; CloseString(). */
28        void OpenString();
29        void AppendSegment(char * segment, int segment_lgth);
30        char * CloseString();  /* Return the pointer to the constructed string. */
31private:
32        /* The initial buffer is allocated as part of the StringPool object.
33           For stack allocated StringPools that do not exceed the initial
34           BasePoolSize, this completely eliminates the overhead and memory
35           fragmentation associated with calls to new and delete. */
36        struct buffer_node {
37                buffer_node * more_buffers;
38                size_t buffer_size;
39                char buffer[BasePoolSize];
40        };
41        buffer_node node1;
42        buffer_node * current_node;
43        size_t total_size;
44        char * insertion_ptr;
45        size_t space_avail;
46        char * opened_string_ptr;
47
48        void ExtendPool();  /* Adds a new buffer to the pool. */
49};
50
51template <int BasePoolSize, int ExpansionPercent>
52StringPool<BasePoolSize, ExpansionPercent>::StringPool() {
53        node1.more_buffers = NULL;
54        node1.buffer_size = BasePoolSize;
55        total_size = node1.buffer_size;
56        insertion_ptr = (char *) &(node1.buffer);
57        space_avail = node1.buffer_size;
58        opened_string_ptr = NULL; /* not open */
59        current_node = &node1;
60}
61
62template <int BasePoolSize, int ExpansionPercent>
63StringPool<BasePoolSize, ExpansionPercent>::~StringPool() {
64        while (current_node != &node1) {
65                buffer_node * allocated_node = current_node;
66                current_node = allocated_node->more_buffers;
67                free(allocated_node);
68        }
69}
70
71template <int BasePoolSize, int ExpansionPercent>
72void StringPool<BasePoolSize, ExpansionPercent>::ExtendPool() {
73        size_t new_buffer_size = (size_t) ((total_size * ExpansionPercent)/100);
74        buffer_node * new_node = (buffer_node *) malloc(sizeof(buffer_node) + new_buffer_size - BasePoolSize);
75        if (new_node == NULL) {
76                fprintf(stderr, "Allocation failure in StringPool<BasePoolSize, ExpansionPercent>::ExtendPool\n");
77                exit(-1);
78        }
79        new_node->more_buffers = current_node;
80        new_node->buffer_size = new_buffer_size;
81        total_size += new_buffer_size;
82        current_node = new_node;
83        if (opened_string_ptr != NULL) {
84                size_t open_string_prefix_size = (size_t) insertion_ptr - (size_t) opened_string_ptr;
85                memcpy(new_node->buffer, opened_string_ptr, open_string_prefix_size);
86                insertion_ptr = &(new_node->buffer[open_string_prefix_size]);
87                opened_string_ptr = new_node->buffer;
88                space_avail = new_buffer_size - open_string_prefix_size;
89        }
90        else {
91                insertion_ptr = new_node->buffer;
92                space_avail = new_buffer_size;
93        }
94//#ifdef DEBUG
95//      printf("ExtendPool() called: space_avail = %i\n", space_avail);
96//#endif
97}
98
99template <int BasePoolSize, int ExpansionPercent>
100char * StringPool<BasePoolSize, ExpansionPercent>::Insert(const char * s, int lgth) {
101        int total_lgth = lgth + 1;
102        while (total_lgth > space_avail) ExtendPool();
103        memcpy(insertion_ptr, s, lgth);
104        char * this_string_ptr = insertion_ptr;
105        insertion_ptr[lgth] = '\0';
106        insertion_ptr += total_lgth;
107        space_avail -= total_lgth;
108//#ifdef DEBUG
109//      printf("Insert(%s, %i)\n", this_string_ptr, lgth);
110//#endif
111        return this_string_ptr;
112}
113
114template <int BasePoolSize, int ExpansionPercent>
115char * StringPool<BasePoolSize, ExpansionPercent>::Insert(const char * s, int lgth, int advance_bit) {
116        int total_lgth = lgth + advance_bit;
117        while (total_lgth > space_avail) ExtendPool();
118        memcpy(insertion_ptr, s, lgth);
119        char * this_string_ptr = insertion_ptr;
120        memset(insertion_ptr + lgth, 0, advance_bit);
121        insertion_ptr += total_lgth;
122        space_avail -= total_lgth;
123//#ifdef DEBUG
124//      printf("Insert(%s, %i)\n", this_string_ptr, lgth);
125//#endif
126        return this_string_ptr;
127}
128
129template <int BasePoolSize, int ExpansionPercent>
130void StringPool<BasePoolSize, ExpansionPercent>::OpenString() {
131        opened_string_ptr = insertion_ptr;
132}
133
134template <int BasePoolSize, int ExpansionPercent>
135void StringPool<BasePoolSize, ExpansionPercent>::AppendSegment(char * segment, int segment_lgth) {
136        /* Make sure that there is length for this segment plus null byte. */
137        while (segment_lgth + 1 > space_avail) ExtendPool();
138        memcpy(insertion_ptr, segment, segment_lgth);
139        insertion_ptr += segment_lgth;
140        space_avail -= segment_lgth;
141}
142
143template <int BasePoolSize, int ExpansionPercent>
144char * StringPool<BasePoolSize, ExpansionPercent>::CloseString() {
145        insertion_ptr[0] = '\0';
146        insertion_ptr++;
147        space_avail--;
148        char * this_string_ptr = opened_string_ptr;
149        opened_string_ptr = NULL;
150        return this_string_ptr;
151}
152#endif
Note: See TracBrowser for help on using the repository browser.