]> git.donarmstrong.com Git - lilypond.git/blob - flower/string.cc
* The grand 2005-2006 replace.
[lilypond.git] / flower / string.cc
1 /*
2   string.cc - implement String
3
4   (c) 1997--2006 Han-Wen Nienhuys & Jan Nieuwenhuizen
5 */
6
7 #ifndef _GNU_SOURCE // we want memmem
8 #define _GNU_SOURCE
9 #endif
10
11 #include "string.hh"
12
13 #include <cstdlib>
14 #include <cstdio>
15 #include <cassert>
16 #include <cstring>
17
18 #include <iostream>
19 using namespace std;
20
21 #include "libc-extension.hh"
22 #include "string-convert.hh"
23
24 #ifdef STRING_DEBUG
25 void *mymemmove (void *dest, void const *src, size_t n);
26 #define memmove mymemmove
27 #endif
28
29 // return array, alloced with new.
30 Byte *
31 String::get_copy_byte () const
32 {
33   Byte const *src = strh_.to_bytes ();
34   Byte *dest = new Byte[strh_.length () + 1];
35   memcpy (dest, src, strh_.length () + 1);
36   return dest;
37 }
38
39 char *
40 String::get_copy_str0 () const
41 {
42   return (char *)get_copy_byte ();
43 }
44
45 \f
46 /*
47   copying, constructing.
48 */
49 String &
50 String::operator = (String const &source)
51 {
52   strh_ = source.strh_;
53   return *this;
54 }
55
56 String::String (Byte const *byte, int len_i)
57 {
58   strh_.set (byte, len_i);
59 }
60
61 /**
62    @see
63    String_convert::
64 */
65 String
66 to_string (char c, int n)
67 {
68   return String_convert::char_string (c, n);
69 }
70
71 String
72 to_string (double f, char const *format)
73 {
74   return String_convert::double_string (f, format);
75 }
76
77 String
78 to_string (int i, char const *format)
79 {
80   return String_convert::int_string (i, format);
81 }
82
83 String
84 to_string (bool b)
85 {
86   return String_convert::bool_string (b);
87 }
88 String
89 to_string (long b)
90 {
91   return String_convert::long_string (b);
92 }
93
94 String
95 to_string (char const *format, ...)
96 {
97   va_list args;
98   va_start (args, format);
99   String str = String_convert::vform_string (format, args);
100   va_end (args);
101   return str;
102 }
103
104 \f
105 void
106 String::append (String s)
107 {
108   strh_.append (s.to_bytes (), s.length ());
109 }
110 void
111 String::operator += (String s)
112 {
113   append (s);
114 }
115
116 void
117 String::prepend (String s)
118 {
119   s += *this;
120   *this = s;
121 }
122
123 int
124 String::length () const
125 {
126   return strh_.length ();
127 }
128
129 Byte const *
130 String::to_bytes () const
131 {
132   return strh_.to_bytes ();
133 }
134
135 Byte *
136 String::get_bytes ()
137 {
138   return strh_.get_bytes ();
139 }
140
141 char *
142 String::get_str0 ()
143 {
144   return strh_.get_str0 ();
145 }
146
147 bool
148 String::is_empty () const
149 {
150   return !length ();
151 }
152 /**
153    Do a signed comparison,  analogous to memcmp;
154 */
155 int
156 String::compare (String const &s1, String const &s2)
157 {
158   Byte const *p1 = s1.to_bytes ();
159   Byte const *p2 = s2.to_bytes ();
160   if (p1 == p2)
161     return 0;
162
163   /*
164     don't forget the terminating '\0'
165   */
166   int f = min (s1.length (), s2.length ());
167   int cmp_length = 1+ f;
168   int i = memcmp (p1, p2, cmp_length);
169   return i;
170 }
171
172 \f
173 int
174 String::index_last (char const c) const
175 {
176   if (!length ())
177     return -1;
178
179   char const *me = strh_.to_str0 ();
180   char const *p = (char const *)memrchr ((Byte *)me, length (), c);
181   if (p)
182     return p - me;
183   return -1;
184 }
185
186 int
187 String::index_last (char const *string) const // UGK!
188 {
189   assert (false);               // broken
190   int len = strlen (string); // ugrh
191   if (!length () || !len)
192     return -1;
193
194   int next_i = index (string);
195   if (next_i == -1)
196     return -1;
197
198   int index_i = 0;
199   while (next_i >= 0)
200     {
201       index_i += next_i;
202       next_i = right_string (length () - index_i - len).index (string);
203     }
204   return index_i;
205 }
206
207 /** find  a character.
208
209 @return
210 the index of the leftmost character #c# (0 <= return < length ()),
211 or   -1 if not found.
212
213 ? should return length ()?, as in string.left_string (index (delimiter))
214 */
215 int
216 String::index (char c) const
217 {
218   char const *me = strh_.to_str0 ();
219   char const *p = (char const *) memchr (me, c, length ());
220   if (p)
221     return p - me;
222   return -1;
223 }
224
225 /**
226    find a substring.
227
228    @return
229    index of leftmost occurrence of #searchfor#
230 */
231 int
232 String::index (String searchfor) const
233 {
234   char const *me = strh_.to_str0 ();
235
236   char const *p
237     = (char const *) memmem (me, length (),
238                              searchfor.to_str0 (), searchfor.length ());
239
240   if (p)
241     return p - me;
242
243   return -1;
244 }
245
246 /** find chars of a set.
247
248 @return
249
250 the index of the leftmost occurance of an element of #set#.  -1 if
251 nothing is found.
252 */
253 int
254 String::index_any (String set) const
255 {
256   int n = length ();
257   if (!n)
258     return -1;
259
260   void const *me = (void const *) strh_.to_str0 ();
261   for (int i = 0; i < set.length (); i++)
262     {
263       char *found = (char *) memchr (me, set[i], n);
264       if (found)
265         return found - (char const *)me;
266     }
267   return -1;
268 }
269 \f
270 String
271 String::left_string (int n) const
272 {
273   if (n >= length ())
274     return *this;
275
276   String retval;
277   if (n < 1)
278     return retval;
279
280   retval = *this;
281   retval.strh_.trunc (n);
282   return retval;
283 }
284
285 String
286 String::right_string (int n) const
287 {
288   if (n > length ())
289     return *this;
290
291   if (n < 1)
292     return "";
293
294   return String (strh_.to_bytes () + length () - n, n);
295 }
296
297 String
298 String::nomid_string (int index_i, int n) const
299 {
300   if (index_i < 0)
301     {
302       n += index_i;
303       index_i = 0;
304     }
305   if (n <= 0)
306     return *this;
307
308   return left_string (index_i) + right_string (length () - index_i - n);
309 }
310
311 String
312 String::cut_string (int index_i, int n) const
313 {
314   if (index_i < 0)
315     {
316       n += index_i;
317       index_i = 0;
318     }
319
320   if (!length () || (index_i < 0) || (index_i >= length ()) || (n < 1))
321     return String ();
322
323   if ((n > length ()) || (index_i + n > length ()))
324     n = length () - index_i;
325
326   return String (to_bytes () + index_i, n);
327 }
328 \f
329
330 void
331 String::to_upper ()
332 {
333   strnupr (get_str0 (), length ());
334 }
335
336 void
337 String::to_lower ()
338 {
339   strnlwr (get_str0 (), length ());
340 }
341
342 void
343 String::reverse ()
344 {
345   memrev (get_bytes (), length ());
346 }
347
348 int
349 String::to_int () const
350 {
351   return String_convert::dec2int (*this);
352 }
353
354 double
355 String::to_double () const
356 {
357   return String_convert::dec2double (*this);
358 }
359
360 #ifdef STREAM_SUPPORT
361 ostream &
362 operator << (ostream &os, String d)
363 {
364   d.print_on (os);
365   return os;
366 }
367
368 void
369 String::print_on (ostream &os) const
370 {
371   if (!strh_.is_binary_bo ())
372     os << to_str0 ();
373   else
374     for (int i = 0; i < length (); i++)
375       os << (Byte) (*this)[ i ];
376 }
377 #endif
378
379 String
380 String::substitute (String find, String replace)
381 {
382   int n = find.length ();
383   int m = replace.length ();
384   for (int i = index (find), j = 0; i > -1;
385        i = right_string (length () - j).index (find))
386     {
387       *this = left_string (i + j)
388         + replace
389         + right_string (length () - j - i - n);
390       j += i + m;
391     }
392   return *this;
393 }
394
395 String
396 String::substitute (char find, char replace)
397 {
398   for (int i = index (find); i > - 1; i = index (find))
399     (*this)[i] = replace;
400   return *this;
401 }