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