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