]> git.donarmstrong.com Git - lilypond.git/blob - flower/string.cc
8a53710dcb34ee804a3f36b0154815d9c4cfa382
[lilypond.git] / flower / string.cc
1 /*
2   PROJECT: FlowerSoft C++ library
3   FILE   : string.cc
4
5   Rehacked by HWN 3/nov/95
6   removed String &
7   introduced Class String_handle
8   */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <assert.h>
15
16 #include "string.hh"
17
18
19 static char* 
20 strlwr( char* s )
21 {
22     char* p = s;
23
24     while( *p )
25         {
26         *p = tolower( *p );    /* a macro on some compilers */
27         p++;
28         }
29     return s;
30 }
31
32 static char* 
33 strupr( char* s )
34 {
35     char* p = s;
36
37     while( *p )
38         {
39         *p = toupper( *p );    /* a macro on some compilers */
40         p++;
41         }
42     return s;
43 }
44
45 String::String(Rational r)
46 {
47     char * n = Itoa(r.numerator()); // LEAK????
48     
49     *this = n;
50     if (r.denominator() != 1) {
51         char * d = Itoa(r.denominator());
52         *this +=  String( '/' ) + String(d);
53         //delete d;
54     }
55 /*    delete n;
56     */
57 }
58
59 // return array, alloced with new.
60 Byte*
61 String::copy_by_p() const
62 {
63     Byte const* src = strh_.by_c_l();
64     Byte* dest = new Byte[strh_.length_i() + 1];
65     memmove( dest, src, strh_.length_i() + 1 );
66     return dest;    
67 }
68
69 void
70 String::printOn(ostream& os) const
71 {
72     if ( length_i() == strlen( ch_c_l() ) )
73         os << ch_c_l();
74     else
75         for ( int i = 0; i < length_i(); i++ )
76             os << (Byte)(*this)[ i ];
77 }
78
79 String::String (bool b)
80 {
81     *this = (char const* ) (b ? "true" : "false");
82 }
83 String::String( char const* source )
84 {   
85     assert(source);    
86     strh_ = source;    
87 }
88
89 String::String( Byte const* by_l, int length_i )
90 {   
91     assert( !length_i || by_l );
92     strh_.set( by_l, length_i );    
93 }
94
95 void
96 String::operator +=(String s)
97 {
98     strh_.append( s.by_c_l(), s.length_i() );
99 }
100
101 int
102 String::length_i() const
103 {
104     return strh_.length_i();
105 }
106
107 String::String(char c,  int n)
108 {
109     int l = n;
110     assert(n >= 0 && n <= 80); // what the fuck is 80?
111 //min(max( n, 0 ), 80); 
112     char s[81];
113     memset(s, c, l);
114     s[l] = 0;
115 //    strh_ = s;
116     strh_.set( (Byte*)s, n );
117 }
118
119 String::String(int i)
120 {
121     char digits[ 81 ];             // who the fuck is 80???
122     digits[ 0 ] = '\0';
123     sprintf(digits, "%d", i );     // assume radix 10
124     strh_ = digits;
125 }
126
127 String::String( const int i, const int n, char const c )
128 {
129     char fillChar = c;
130     if ( fillChar)
131         fillChar = '0';
132
133     String v( i );
134     
135     String str = String( fillChar, n - v.length_i() ) + String( v );
136     strh_.set( str.by_c_l(), str.length_i() );
137 }
138
139 Byte const*
140 String::by_c_l() const
141 {
142     return strh_.by_c_l();
143 }
144
145 char const*
146 String::ch_c_l() const
147 {
148     return strh_.ch_c_l();
149 }
150
151 Byte*
152 String::by_l()
153 {
154     return strh_.by_l();
155 }
156
157 char*
158 String::ch_l()
159 {
160     return strh_.ch_l();
161 }
162
163 // signed comparison,  analogous to memcmp;
164 int
165 String::compare(String const& s1, String const& s2 ) 
166 {
167     Byte const* p1 = s1.by_c_l();
168     Byte const* p2 = s2.by_c_l();
169     if ( p1 == p2 )
170         return 0;
171
172     int i1 = s1.length_i();
173     int i2 = s2.length_i();
174     int i = i1 <? i2;
175
176     if (! i ) 
177         return 0;
178         
179     int result =  memcmp( p1, p2, i );
180     
181     return (result)? result : i1 - i2;
182 }
183
184
185 int
186 String::lastPos( char const c ) const
187 {
188     // not binary safe
189     assert( length_i() == strlen( ch_c_l() ) );
190     char const* me = strh_.ch_c_l();
191     int pos = 0;
192     if ( length_i() )
193         {
194         char const* p = strrchr(me, c );
195         if ( p )
196             pos = p - me + 1;
197         }
198     return pos;
199 }
200
201 int
202 String::lastPos( char const* string ) const
203 {
204     // not binary safe
205     assert( length_i() == strlen( ch_c_l() ) );
206     int pos = 0;
207     int length = strlen( string );
208     if ( length_i() && length )
209         {
210         int nextpos = this->pos( string );
211         while( nextpos )
212             {
213             pos += nextpos;
214             nextpos = right( length_i() - pos - length + 1 ).pos( string );
215             }
216         }
217     return pos;
218 }
219
220 // find c
221 // return 0 if not found. 
222
223 // ? should return length_i()?, as in string.left(pos(delimiter))
224 int
225 String::pos(char c ) const
226 {
227     // not binary safe
228     assert( length_i() == strlen( ch_c_l() ) );
229     char const* me = strh_.ch_c_l();
230     int pos = 0;
231     if ( length_i() )
232         {
233         char const* p = strchr( me, c );
234         if ( p )
235             pos = p - me + 1;
236         }
237     return pos;
238 }
239
240 // find searchfor. (what if this == "" && searchfor == "") ???
241 int
242 String::pos( char const* searchfor ) const
243 {
244     // not binary safe
245     assert( length_i() == strlen( ch_c_l() ) );
246     char const* me = strh_.ch_c_l();
247     int pos = 0;
248     if ( length_i() && searchfor)
249         {
250         char const* p = strstr(me, searchfor);
251         if ( p )
252             pos = p - me + 1;
253         }
254     return pos;
255 }
256
257 // find chars of a set.
258 int
259 String::posAny( char const* string ) const
260 {
261     // not binary safe
262     assert( length_i() == strlen( ch_c_l() ) );
263     int pos = 0;
264     char const* s = (char const* )strh_.ch_c_l();
265     if ( length_i() && string )
266         {
267         char const* p = strpbrk( s, string );
268         if ( p )
269             pos = p - s + 1;
270         }
271     return pos;
272 }
273
274 String
275 String::left( int n ) const
276 {
277     if (n >= length_i())
278         return *this;
279
280     String retval;      
281     if (n < 1)
282         return retval;
283     
284     retval = *this;
285     retval.strh_.trunc(n);
286     return retval;
287 }
288
289
290 // n rightmst chars
291 String
292 String::right( int n ) const
293 {
294     if (n > length_i())
295         return *this;
296     
297     if ( n < 1)
298         String(); 
299     
300     return String( strh_.by_c_l() + length_i() - n, n ); 
301 }
302
303
304 String
305 String::nomid( const int pos, const int n ) const
306 {
307     String retval;
308         
309     if ( pos < 1 )
310         return String("");
311     if ( pos > length_i())
312         return *this;
313     
314     return String( String( left( pos - 1 ) ) + right( length_i() - pos - n + 1 ));
315 }
316
317
318 String
319 String::mid( int pos, int n ) const
320 {
321     // HWN. This SUX: JCN: yep, please change me + all my invocations
322     // pos 1 == strh_->string[ 0 ];
323     // pos 0 allowed for convenience
324     if ( !length_i() || ( pos < 0 ) || ( pos > length_i() ) && ( n < 1 ) )
325         return String();
326
327     // overflow...
328     if ( ( n > length_i() ) ||  ( pos + n - 1 > length_i() ) )
329         n = length_i() - pos + 1;
330
331     return String( by_c_l() + pos -1, n );
332 }
333
334
335 // to  uppercase
336 String
337 String::upper()
338 {
339     // not binary safe
340     assert( length_i() == strlen( ch_c_l() ) );
341     char *s = strh_.by_l();
342     strupr( s );
343     return *this;
344 }
345
346
347 // to lowercase
348 String 
349 String::lower()
350 {
351     // not binary safe
352     assert( length_i() == strlen( ch_c_l() ) );
353     char* s = strh_.by_l();
354     strlwr(s);
355     return *this;
356 }
357
358 String::String (double f, char const* fmt)
359 {
360     /* worst case would be printing HUGE (or 1/HUGE), which is approx
361        2e318, this number would have approx 318 zero's in its string.
362
363       1024 is a safe length for the buffer
364       */
365
366     char buf[1024]; 
367     if (!fmt)
368         sprintf(buf, "%f", f);
369     else
370         sprintf(buf, fmt,f);
371     *this = buf;
372 }
373
374 long
375 String::value() const
376 {
377     long l =0;
378     if (length_i()) {
379         int conv = sscanf(strh_.ch_c_l(), "%ld", &l);
380         assert(conv);
381     }
382     return l;
383 }
384
385 double
386 String::fvalue() const
387 {
388     double d =0;
389     if (length_i()) {
390         int conv = sscanf(strh_.ch_c_l(), "%lf", &d);
391         assert(conv);
392     }
393     return d;
394 }
395
396
397 String quoteString( String msg, String quote)
398 {
399     return msg + " `" + quote  + "' ";
400 }
401
402
403 Byte*
404 strrev( Byte* by_l, int length_i )
405 {
406   Byte by;
407   Byte* left_by_l = by_l;
408   Byte* right_by_l = by_l + length_i;
409
410   while ( right_by_l > left_by_l ) {
411     by = *left_by_l;
412     *left_by_l++ = *right_by_l;
413     *right_by_l-- = by;
414   }
415   return by_l;
416 }
417
418
419 String 
420 String::reversed() const
421 {
422     String str = *this;
423     strrev( str.by_l(), str.length_i() );
424     return str;    
425 }