]> git.donarmstrong.com Git - lilypond.git/blob - flower/stringutil.hh
b7503b7d2a304a91381a164029248bec3cfa131f
[lilypond.git] / flower / stringutil.hh
1 #ifndef STRINGUTIL_HH
2 #define STRINGUTIL_HH
3 #include <assert.h>
4
5 #ifndef EVELYN
6 #define NDEBUG BLONDE
7   // switching into "blonde" mode
8   // i trust stringclass nowadays.
9 #endif
10
11 class String_handle;
12 /// Internal String struct
13 class StringData {
14     // GNU malloc: storage overhead is 8 bytes anyway.
15     const int INITIALMAX = 8;  
16
17 friend class String_handle;
18     int maxlen; // maxlen is arraysize-1
19     
20     int length;
21     char* string;
22     int references;
23
24     /// init to ""
25     StringData() {
26         references=0;
27         maxlen = INITIALMAX;
28         string = new char[maxlen + 1];
29         string[0] = 0;
30         length = 0;
31     }
32
33     /// init from src. Conservative allocation.
34     StringData(StringData const &src) {
35         references=0;   
36         maxlen = length = src.length;           
37         string = new char[maxlen+1]; // should calc GNU 8byte overhead.         
38         strcpy(string, src.string);     
39     }
40     
41     ~StringData() {
42         assert(references == 0);
43         delete[] string;
44     }
45
46
47     void setmax(int j) {        
48         OKW();
49         if (j > maxlen) {
50             delete string;
51             maxlen = j;
52             string = new char[maxlen + 1];
53         
54             string[0] = 0;
55             length = 0;
56         }
57     }
58     /** POST: maxlen >= j.
59       IN: j, maximum stringlength.    
60       contents thrown away.
61     */
62     ///
63     void remax(int j) {
64         OKW();
65         if (j > maxlen) {
66             maxlen = j;
67             char *p = new char[maxlen + 1];         
68             strcpy(p,string);       
69             delete[] string;
70             string = p;
71         //    length = strlen(string);
72         }
73     }
74     /** POST: maxlen >= j.
75       IN: j, maximum stringlength.
76       contents are kept if it grows.
77       */    
78     /// check if writeable.
79     void OKW() {
80
81         assert (references == 1);
82
83     }
84
85     /// check state.
86     void OK() {
87         assert(strlen(string) == size_t(length));
88         assert(maxlen >= length);
89         assert(bool(string));
90         assert(references >= 1);
91     }
92
93     // needed?
94     void update() {
95         length  = strlen (string);
96     }
97
98     /// reduce memory usage.
99     void tighten() { // should be dec'd const
100         maxlen = length;
101         char *p = new char[maxlen + 1];     
102         strcpy(p,string);           
103         delete[] string;
104         string = p;             
105     }
106
107     // assignment.
108     void set(const char *s) {
109         OKW();
110
111         assert(s);
112
113         length = strlen (s);
114         remax(length);
115         strcpy(string,s);
116     }
117     
118     /// concatenation.
119     void operator += (const char *s) {
120         OK();
121         OKW();
122         int old = length;
123         
124         length += strlen(s);
125         remax (length);
126         strcpy(string + old, s);        
127     }
128
129     /// the array itself
130     operator const char *() const { return string; }
131
132     // idem, non const
133     char *array_for_modify() {
134         OKW();
135         return string;
136     }
137     void trunc(int j) {
138         OKW(); 
139         assert(j >= 0 && j <= length);
140         string[j] = 0;
141         length = j;
142     }
143
144     /** not really safe. Can alter length without StringData knowing it.
145       */
146     char &operator [](int j) {
147         assert(j >= 0 && j <= length);
148         return string[j] ; 
149     }
150
151     char operator [](int j) const {
152         assert(j >= 0 && j <= length);
153         return string[j]; 
154     }
155 };
156
157 /**
158    the data itself. Handles simple tasks (resizing, resetting)
159  */
160 /****************************************************************/
161 /// ref. counting for strings
162 class String_handle {
163     StringData* data;
164     
165     /// decrease ref count. Named kind of like a Tanenbaum semafore 
166     void down() { if (!(--data->references)) delete data; data = 0; }
167
168     /// increase ref count
169     void up(StringData *d) { data=d; data->references ++; }
170     
171     /** make sure data has only one reference.      
172        POST: data->references == 1
173       */
174     void copy() {
175         if (data->references !=1){
176             StringData *newdata = new StringData(*data);
177             down();
178             up(newdata);
179         }
180     }
181     
182 public:
183
184     String_handle() {
185         up(new StringData);
186     }
187     ~String_handle() {  
188         down();
189     }    
190     String_handle(String_handle const & src) {  
191         up(src.data);
192     }
193
194     /// retrieve the actual array.
195     operator const char *() const { return *data; }    
196     char *array_for_modify() {
197         copy();
198         return data->array_for_modify();
199     }
200     
201     void operator =(String_handle const &src) {
202         if (this == &src)
203             return;
204         down();
205         up(src.data);
206     }
207     
208     void operator += (const char *s) {  
209         copy();
210         *data += s;
211     }    
212
213     
214     char operator[](int j) const { return (*data)[j]; }
215
216     // !NOT SAFE!
217     // don't use this for loops. Use array_for_modify()
218     char &operator[](int j) {
219         copy();         // hmm. Not efficient
220         return data->array_for_modify()[j];
221     }
222
223     void operator = (char const *p) {
224         copy();
225         data->set(p);
226     }
227                                
228     void trunc(int j) { copy(); data->trunc(j); }
229     int len() const { return data->length; }
230 };
231 /**
232    handles ref. counting, and provides a very thin
233    interface using char *
234  */
235
236
237 #ifdef NDEBUG
238 #if (NDEBUG == BLONDE)
239 #undef NDEBUG
240 #endif
241 #endif
242
243
244
245 #endif // STRINGUTIL_HH