]> git.donarmstrong.com Git - lilypond.git/blob - flower/string-convert.cc
*** empty log message ***
[lilypond.git] / flower / string-convert.cc
1 /*
2   PROJECT: FlowerSoft C++ library
3   FILE   : string-convert.cc
4
5   --*/
6
7 #include "string-convert.hh"
8
9 #include <publib.h>
10 #include <cstring>
11 #include <cstdio>
12 using namespace std;
13
14 #include "libc-extension.hh"
15 #include "rational.hh"
16 #include "array.hh"
17
18 /**
19    A safe length for stringconversion buffers.
20
21    worst case would be %f printing HUGE (or 1/HUGE), which is approx
22    2e318, this number would have approx 318 zero's in its string.
23
24    Should enlarge buff dynamically.
25
26    @see
27    man 3 snprintf
28 */
29 static const int STRING_BUFFER_LEN = 1024;
30
31 std::string
32 String_convert::bool_string (bool b)
33 {
34   return std::string (b ? "true" : "false");
35 }
36
37 std::string
38 String_convert::bin2hex (std::string bin_string)
39 {
40   std::string str;
41   Byte const *byte = (Byte const*)bin_string.data ();
42   for (ssize i = 0; i < bin_string.length (); i++)
43     {
44       str += to_string ((char)nibble2hex_byte (*byte >> 4));
45       str += to_string ((char)nibble2hex_byte (*byte++));
46     }
47   return str;
48 }
49
50 int
51 String_convert::bin2int (std::string bin_string)
52 {
53   return bin2unsigned (bin_string);
54 }
55
56 unsigned
57 String_convert::bin2unsigned (std::string bin_string)
58 {
59   assert (bin_string.length () <= (int)sizeof (unsigned));
60
61   unsigned result_u = 0;
62   for (ssize i = 0; i < bin_string.length (); i++)
63     {
64       result_u <<= 8;
65       result_u += (Byte)bin_string[ i ];
66     }
67   return result_u;
68 }
69
70 // breendet imp from std::string
71 int
72 String_convert::dec2int (std::string dec_string)
73 {
74   if (!dec_string.length ())
75     return 0;
76
77   long l = 0;
78   int conv = sscanf (dec_string.c_str (), "%ld", &l);
79   assert (conv);
80
81   return (int)l;
82 }
83
84 std::string
85 String_convert::i64_string (I64 i64, char const *fmt)
86 {
87   char buffer[STRING_BUFFER_LEN];
88   snprintf (buffer, STRING_BUFFER_LEN,
89             (fmt ? fmt : "%Ld"), i64); // assume radix 10
90   return std::string (buffer);
91 }
92 // breendet imp from std::string
93 double
94 String_convert::dec2double (std::string dec_string)
95 {
96   if (!dec_string.length ())
97     return 0;
98   double d = 0;
99   int conv = sscanf (dec_string.c_str (), "%lf", &d);
100   assert (conv);
101   return d;
102 }
103
104 int
105 String_convert::hex2bin (std::string hex_string, std::string &bin_string_r)
106 {
107   if (hex_string.length () % 2)
108     hex_string = "0" + hex_string;
109
110   bin_string_r = "";
111   Byte const *byte = (Byte const*) hex_string.data ();
112   ssize i = 0;
113   while (i < hex_string.length ())
114     {
115       int high_i = hex2nibble (*byte++);
116       int low_i = hex2nibble (*byte++);
117       if (high_i < 0 || low_i < 0)
118         return 1; // illegal char
119       bin_string_r += to_string ((char) (high_i << 4 | low_i), 1);
120       i += 2;
121     }
122   return 0;
123 }
124
125 std::string
126 String_convert::hex2bin (std::string hex_string)
127 {
128   std::string str;
129   //  silly, asserts should alway be "on"!
130   //    assert (!hex2bin (hex_string, str) );
131   int error_i = hex2bin (hex_string, str);
132   assert (!error_i);
133   return str;
134 }
135
136 int
137 String_convert::hex2nibble (Byte byte)
138 {
139   if (byte >= '0' && byte <= '9')
140     return byte - '0';
141   if (byte >= 'A' && byte <= 'F')
142     return byte - 'A' + 10;
143   if (byte >= 'a' && byte <= 'f')
144     return byte - 'a' + 10;
145   return -1;
146 }
147
148 // stupido.  Should use int_string ()
149 std::string
150 String_convert::int2dec (int i, int length_i, char ch)
151 {
152   char fill_char = ch;
153   if (fill_char)
154     fill_char = '0';
155
156   // ugh
157   std::string dec_string = to_string (i);
158
159   // ugh
160   return to_string (fill_char, length_i - dec_string.length ()) + dec_string;
161 }
162
163 // stupido.  Should use int_string ()
164 std::string
165 String_convert::unsigned2hex (unsigned u, ssize length, char fill_char)
166 {
167   std::string str;
168   if (!u)
169     str = "0";
170
171 #if 1 // both go...
172   while (u)
173     {
174       str = to_string ((char) ((u % 16)["0123456789abcdef"])) + str;
175       u /= 16;
176     }
177 #else
178   str += int_string (u, "%x");  // hmm. %lx vs. %x -> portability?
179 #endif
180
181   str = to_string (fill_char, length - str.length ()) + str;
182   while ((str.length () > length) && (str[ 0 ] == 'f'))
183     str = str.substr (2);
184
185   return str;
186 }
187
188 std::string
189 String_convert::int2hex (int i, int length_i, char fill_char)
190 {
191   return unsigned2hex ((unsigned)i, length_i, fill_char);
192 }
193
194 Byte
195 String_convert::nibble2hex_byte (Byte byte)
196 {
197   if ((byte & 0x0f) <= 9)
198     return (byte & 0x0f) + '0';
199   else
200     return (byte & 0x0f) - 10 + 'a';
201 }
202 /**
203    Convert an integer to a string
204
205    @param
206    #fmt# is a printf style format, default assumes "%d" as format.
207 */
208 std::string
209 String_convert::int_string (int i, char const *fmt)
210 {
211   char buffer[STRING_BUFFER_LEN];
212   snprintf (buffer, STRING_BUFFER_LEN,
213             (fmt ? fmt : "%d"), i); // assume radix 10
214   return std::string (buffer);
215 }
216
217 std::string
218 String_convert::form_string (char const *format, ...)
219 {
220   va_list args;
221   va_start (args, format);
222   char buffer[STRING_BUFFER_LEN];
223   vsnprintf (buffer, STRING_BUFFER_LEN, format, args);
224   va_end (args);
225   return std::string (buffer);
226 }
227
228 std::string
229 String_convert::vform_string (char const *format, va_list args)
230 {
231   char buffer[STRING_BUFFER_LEN];
232   vsnprintf (buffer, STRING_BUFFER_LEN, format, args);
233   return std::string (buffer);
234 }
235
236 /**
237    Convert a double to a string.
238
239    @param #fmt# is a printf style format, default assumes "%lf" as format
240 */
241 std::string
242 String_convert::double_string (double f, char const *fmt)
243 {
244   char buf[STRING_BUFFER_LEN];
245
246   snprintf (buf, STRING_BUFFER_LEN, fmt ? fmt : "%f", f);
247   return std::string (buf);
248 }
249
250 /**
251    Make a string from a single character.
252
253    @param
254    #n# is a repetition count, default value is 1
255 */
256 std::string
257 String_convert::char_string (char c, int n)
258 {
259   n = n >= 0 ? n : 0;
260   char *ch = new char[ n ];
261   memset (ch, c, n);
262 #if STD_STRING
263   std::string s (ch, n);
264 #else
265   std::string s (ch, n);
266 #endif
267   delete[] ch;
268   return s;
269 }
270
271 std::string
272 String_convert::rational_string (Rational r)
273 {
274   return r.to_string ();
275 }
276
277 std::string
278 String_convert::pointer_string (void const *l)
279 {
280   char buffer[STRING_BUFFER_LEN];
281   snprintf (buffer, STRING_BUFFER_LEN, "%p", l); // assume radix 10
282   return std::string (buffer);
283 }
284
285 /**
286    Convert a double to a string.
287
288    @param
289    #n# is the number of nonzero digits
290 */
291 std::string
292 String_convert::precision_string (double x, int n)
293 {
294   std::string format = "%." + to_string (max (0, n - 1)) + "e";
295   std::string str = double_string (abs (x), format.c_str ());
296
297   int exp = dec2int (str.substr (str.length () - 3));
298   str = str.substr (0, str.length () - 4);
299
300   while (str[str.length () - 1] == '0')
301     str = str.substr (0, str.length () - 1);
302   if (str[str.length () - 1] == '.')
303     str = str.substr (0, str.length () - 1);
304
305   if (exp == 0)
306     return (sign (x) > 0 ? str : "-" + str);
307
308   str = str.substr (0, 1) + str.substr (2);
309   ssize dot = 1 + exp;
310   if (dot <= 0)
311     str = "0." + to_string ('0', -dot) + str;
312   else if (dot >= str.length ())
313     str += to_string ('0', dot - str.length ());
314   else if ((dot > 0) && (dot < str.length ()))
315     str = str.substr (0, dot) + "." + str.substr (dot);
316   else
317     assert (0);
318
319   return (sign (x) > 0 ? str : "-" + str);
320 }
321
322 Array<std::string>
323 String_convert::split (std::string str, char c)
324 {
325   Array<std::string> a;
326   ssize i = str.find (c);
327   while (i != NPOS)
328     {
329       std::string s = str.substr (0, i);
330       a.push (s);
331       while (str[++i] == c)
332         ;
333       str = str.substr (i);
334       i = str.find (c);
335     }
336   if (str.length ())
337     a.push (str);
338   return a;
339 }
340
341 std::string
342 String_convert::long_string (long l)
343 {
344   char s[STRING_BUFFER_LEN];
345   sprintf (s, "%ld", l);
346   return s;
347 }
348
349 std::string
350 String_convert::pad_to (std::string s, int n)
351 {
352   return s + std::string (max (int(n - s.length ()), 0), ' ');
353 }
354
355 std::string
356 String_convert::to_upper (std::string s)
357 {
358   return strnupr ((char *)s.c_str (), s.length ());
359 }
360
361 std::string
362 String_convert::to_lower (std::string s)
363 {
364   return strnlwr ((char *)s.c_str (), s.length ());
365 }
366
367 std::string
368 String_convert::reverse (std::string s)
369 {
370   return (char*) memrev ((unsigned char *)s.data (), s.length ());
371 }