]> git.donarmstrong.com Git - lilypond.git/blob - flower/string.cc
c4c7d49abf39b1c617b4dbf918ca317ba8ab4ef6
[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 Byte *
135 String::get_bytes ()
136 {
137   return strh_.get_bytes ();
138 }
139
140 char *
141 String::get_str0 ()
142 {
143   return strh_.get_str0 ();
144 }
145
146 bool
147 String::is_empty () const
148 {
149   return !length ();
150 }
151 /**
152    Do a signed comparison,  analogous to memcmp;
153 */
154 int
155 String::compare (String const &s1, String const &s2)
156 {
157   Byte const *p1 = s1.to_bytes ();
158   Byte const *p2 = s2.to_bytes ();
159   if (p1 == p2)
160     return 0;
161
162   /*
163     don't forget the terminating '\0'
164   */
165   int f = min (s1.length (), s2.length ());
166   int cmp_length = 1+ f;
167   int i = memcmp (p1, p2, cmp_length);
168   return i;
169 }
170
171 \f
172 int
173 String::index_last (char const c) const
174 {
175   if (!length ())
176     return -1;
177
178   char const *me = strh_.to_str0 ();
179   char const *p = (char const *)memrchr ((Byte *)me, length (), c);
180   if (p)
181     return p - me;
182   return -1;
183 }
184
185 int
186 String::index_last (char const *string) const // UGK!
187 {
188   assert (false);               // broken
189   int len = strlen (string); // ugrh
190   if (!length () || !len)
191     return -1;
192
193   int next_i = index (string);
194   if (next_i == -1)
195     return -1;
196
197   int index_i = 0;
198   while (next_i >= 0)
199     {
200       index_i += next_i;
201       next_i = right_string (length () - index_i - len).index (string);
202     }
203   return index_i;
204 }
205
206 /** find  a character.
207
208 @return
209 the index of the leftmost character #c# (0 <= return < length ()),
210 or   -1 if not found.
211
212 ? should return length ()?, as in string.left_string (index (delimiter))
213 */
214 int
215 String::index (char c) const
216 {
217   char const *me = strh_.to_str0 ();
218   char const *p = (char const *) memchr (me, c, length ());
219   if (p)
220     return p - me;
221   return -1;
222 }
223
224 /**
225    find a substring.
226
227    @return
228    index of leftmost occurrence of #searchfor#
229 */
230 int
231 String::index (String searchfor) const
232 {
233   char const *me = strh_.to_str0 ();
234
235   char const *p = (char const *)
236     memmem (me, length (), searchfor.to_str0 (), searchfor.length ());
237
238   if (p)
239     return p - me;
240
241   return -1;
242 }
243
244 /** find chars of a set.
245
246 @return
247
248 the index of the leftmost occurance of an element of #set#.  -1 if
249 nothing is found.
250 */
251 int
252 String::index_any (String set) const
253 {
254   int n = length ();
255   if (!n)
256     return -1;
257
258   void const *me = (void const *) strh_.to_str0 ();
259   for (int i = 0; i < set.length (); i++)
260     {
261       char *found = (char *) memchr (me, set[i], n);
262       if (found)
263         return found - (char const *)me;
264     }
265   return -1;
266 }
267 \f
268 String
269 String::left_string (int n) const
270 {
271   if (n >= length ())
272     return *this;
273
274   String retval;
275   if (n < 1)
276     return retval;
277
278   retval = *this;
279   retval.strh_.trunc (n);
280   return retval;
281 }
282
283 String
284 String::right_string (int n) const
285 {
286   if (n > length ())
287     return *this;
288
289   if (n < 1)
290     return "";
291
292   return String (strh_.to_bytes () + length () - n, n);
293 }
294
295 String
296 String::nomid_string (int index_i, int n) const
297 {
298   if (index_i < 0)
299     {
300       n += index_i;
301       index_i = 0;
302     }
303   if (n <= 0)
304     return *this;
305
306   return left_string (index_i) + right_string (length () - index_i - n);
307 }
308
309 String
310 String::cut_string (int index_i, int n) const
311 {
312   if (index_i < 0)
313     {
314       n += index_i;
315       index_i = 0;
316     }
317
318   if (!length () || (index_i < 0) || (index_i >= length ()) || (n < 1))
319     return String ();
320
321   if ((n > length ()) || (index_i + n > length ()))
322     n = length () - index_i;
323
324   return String (to_bytes () + index_i, n);
325 }
326 \f
327
328 void
329 String::to_upper ()
330 {
331   strnupr (get_str0 (), length ());
332 }
333
334 void
335 String::to_lower ()
336 {
337   strnlwr (get_str0 (), length ());
338 }
339
340 void
341 String::reverse ()
342 {
343   memrev (get_bytes (), length ());
344 }
345
346 int
347 String::to_int () const
348 {
349   return String_convert::dec2int (*this);
350 }
351
352 double
353 String::to_double () const
354 {
355   return String_convert::dec2double (*this);
356 }
357
358 #ifdef STREAM_SUPPORT
359 ostream &
360 operator << (ostream &os, String d)
361 {
362   d.print_on (os);
363   return os;
364 }
365
366 void
367 String::print_on (ostream &os) const
368 {
369   if (!strh_.is_binary_bo ())
370     os << to_str0 ();
371   else
372     for (int i = 0; i < length (); i++)
373       os << (Byte) (*this)[ i ];
374 }
375 #endif
376
377 String
378 String::substitute (String find, String replace)
379 {
380   int n = find.length ();
381   int m = replace.length ();
382   for (int i = index (find), j = 0; i > -1;
383        i = right_string (length () - j).index (find))
384     {
385       *this = left_string (i + j)
386         + replace
387         + right_string (length () - j - i - n);
388       j += i + m;
389     }
390   return *this;
391 }
392
393 String
394 String::substitute (char find, char replace)
395 {
396   for (int i = index (find); i > - 1; i = index (find))
397     (*this)[i] = replace;
398   return *this;
399 }