]> git.donarmstrong.com Git - lilypond.git/blob - flower/string.cc
24ba1e2feaa242127a9d359c541afccb49042551
[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
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 = (char const *)
237     memmem (me, length (), searchfor.to_str0 (), searchfor.length ());
238
239   if (p)
240     return p - me;
241
242   return -1;
243 }
244
245 /** find chars of a set.
246
247 @return
248
249 the index of the leftmost occurance of an element of #set#.  -1 if
250 nothing is found.
251 */
252 int
253 String::index_any (String set) const
254 {
255   int n = length ();
256   if (!n)
257     return -1;
258
259   void const *me = (void const *) strh_.to_str0 ();
260   for (int i = 0; i < set.length (); i++)
261     {
262       char *found = (char *) memchr (me, set[i], n);
263       if (found)
264         return found - (char const *)me;
265     }
266   return -1;
267 }
268 \f
269 String
270 String::left_string (int n) const
271 {
272   if (n >= length ())
273     return *this;
274
275   String retval;
276   if (n < 1)
277     return retval;
278
279   retval = *this;
280   retval.strh_.trunc (n);
281   return retval;
282 }
283
284 String
285 String::right_string (int n) const
286 {
287   if (n > length ())
288     return *this;
289
290   if (n < 1)
291     return "";
292
293   return String (strh_.to_bytes () + length () - n, n);
294 }
295
296 String
297 String::nomid_string (int index_i, int n) const
298 {
299   if (index_i < 0)
300     {
301       n += index_i;
302       index_i = 0;
303     }
304   if (n <= 0)
305     return *this;
306
307   return left_string (index_i) + right_string (length () - index_i - n);
308 }
309
310 String
311 String::cut_string (int index_i, int n) const
312 {
313   if (index_i < 0)
314     {
315       n += index_i;
316       index_i = 0;
317     }
318
319   if (!length () || (index_i < 0) || (index_i >= length ()) || (n < 1))
320     return String ();
321
322   if ((n > length ()) || (index_i + n > length ()))
323     n = length () - index_i;
324
325   return String (to_bytes () + index_i, n);
326 }
327 \f
328
329 void
330 String::to_upper ()
331 {
332   strnupr (get_str0 (), length ());
333 }
334
335 void
336 String::to_lower ()
337 {
338   strnlwr (get_str0 (), length ());
339 }
340
341 void
342 String::reverse ()
343 {
344   memrev (get_bytes (), length ());
345 }
346
347 int
348 String::to_int () const
349 {
350   return String_convert::dec2int (*this);
351 }
352
353 double
354 String::to_double () const
355 {
356   return String_convert::dec2double (*this);
357 }
358
359 #ifdef STREAM_SUPPORT
360 ostream &
361 operator << (ostream &os, String d)
362 {
363   d.print_on (os);
364   return os;
365 }
366
367 void
368 String::print_on (ostream &os) const
369 {
370   if (!strh_.is_binary_bo ())
371     os << to_str0 ();
372   else
373     for (int i = 0; i < length (); i++)
374       os << (Byte) (*this)[ i ];
375 }
376 #endif
377
378 String
379 String::substitute (String find, String replace)
380 {
381   int n = find.length ();
382   int m = replace.length ();
383   for (int i = index (find), j = 0; i > -1;
384        i = right_string (length () - j).index (find))
385     {
386       *this = left_string (i + j)
387         + replace
388         + right_string (length () - j - i - n);
389       j += i + m;
390     }
391   return *this;
392 }
393
394 String
395 String::substitute (char find, char replace)
396 {
397   for (int i = index (find); i > - 1; i = index (find))
398     (*this)[i] = replace;
399   return *this;
400 }