lilypond-0.0.1
[lilypond.git] / flower / stringutil.hh
blobb7503b7d2a304a91381a164029248bec3cfa131f
1 #ifndef STRINGUTIL_HH
2 #define STRINGUTIL_HH
3 #include <assert.h>
5 #ifndef EVELYN
6 #define NDEBUG BLONDE
7 // switching into "blonde" mode
8 // i trust stringclass nowadays.
9 #endif
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;
17 friend class String_handle;
18 int maxlen; // maxlen is arraysize-1
20 int length;
21 char* string;
22 int references;
24 /// init to ""
25 StringData() {
26 references=0;
27 maxlen = INITIALMAX;
28 string = new char[maxlen + 1];
29 string[0] = 0;
30 length = 0;
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);
41 ~StringData() {
42 assert(references == 0);
43 delete[] string;
47 void setmax(int j) {
48 OKW();
49 if (j > maxlen) {
50 delete string;
51 maxlen = j;
52 string = new char[maxlen + 1];
54 string[0] = 0;
55 length = 0;
58 /** POST: maxlen >= j.
59 IN: j, maximum stringlength.
60 contents thrown away.
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);
74 /** POST: maxlen >= j.
75 IN: j, maximum stringlength.
76 contents are kept if it grows.
77 */
78 /// check if writeable.
79 void OKW() {
81 assert (references == 1);
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);
93 // needed?
94 void update() {
95 length = strlen (string);
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;
107 // assignment.
108 void set(const char *s) {
109 OKW();
111 assert(s);
113 length = strlen (s);
114 remax(length);
115 strcpy(string,s);
118 /// concatenation.
119 void operator += (const char *s) {
120 OK();
121 OKW();
122 int old = length;
124 length += strlen(s);
125 remax (length);
126 strcpy(string + old, s);
129 /// the array itself
130 operator const char *() const { return string; }
132 // idem, non const
133 char *array_for_modify() {
134 OKW();
135 return string;
137 void trunc(int j) {
138 OKW();
139 assert(j >= 0 && j <= length);
140 string[j] = 0;
141 length = j;
144 /** not really safe. Can alter length without StringData knowing it.
146 char &operator [](int j) {
147 assert(j >= 0 && j <= length);
148 return string[j] ;
151 char operator [](int j) const {
152 assert(j >= 0 && j <= length);
153 return string[j];
158 the data itself. Handles simple tasks (resizing, resetting)
160 /****************************************************************/
161 /// ref. counting for strings
162 class String_handle {
163 StringData* data;
165 /// decrease ref count. Named kind of like a Tanenbaum semafore
166 void down() { if (!(--data->references)) delete data; data = 0; }
168 /// increase ref count
169 void up(StringData *d) { data=d; data->references ++; }
171 /** make sure data has only one reference.
172 POST: data->references == 1
174 void copy() {
175 if (data->references !=1){
176 StringData *newdata = new StringData(*data);
177 down();
178 up(newdata);
182 public:
184 String_handle() {
185 up(new StringData);
187 ~String_handle() {
188 down();
190 String_handle(String_handle const & src) {
191 up(src.data);
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();
201 void operator =(String_handle const &src) {
202 if (this == &src)
203 return;
204 down();
205 up(src.data);
208 void operator += (const char *s) {
209 copy();
210 *data += s;
214 char operator[](int j) const { return (*data)[j]; }
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];
223 void operator = (char const *p) {
224 copy();
225 data->set(p);
228 void trunc(int j) { copy(); data->trunc(j); }
229 int len() const { return data->length; }
232 handles ref. counting, and provides a very thin
233 interface using char *
237 #ifdef NDEBUG
238 #if (NDEBUG == BLONDE)
239 #undef NDEBUG
240 #endif
241 #endif
245 #endif // STRINGUTIL_HH