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