Fixes for GCC 4.3.
[ardour.git] / libs / pbd / convert.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cmath>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #ifndef __STDC_FORMAT_MACROS
24 #define __STDC_FORMAT_MACROS
25 #endif
26 #include <inttypes.h>
27
28 #include "pbd/convert.h"
29
30 #include "i18n.h"
31
32 using std::string;
33 using std::vector;
34 using Glib::ustring;
35
36 namespace PBD {
37
38 string
39 short_version (string orig, string::size_type target_length)
40 {
41         /* this tries to create a recognizable abbreviation
42            of "orig" by removing characters until we meet
43            a certain target length.
44
45            note that we deliberately leave digits in the result
46            without modification.
47         */
48
49
50         string::size_type pos;
51
52         /* remove white-space and punctuation, starting at end */
53
54         while (orig.length() > target_length) {
55                 if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
56                         break;
57                 }
58                 orig.replace (pos, 1, "");
59         }
60
61         /* remove lower-case vowels, starting at end */
62
63         while (orig.length() > target_length) {
64                 if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
65                         break;
66                 }
67                 orig.replace (pos, 1, "");
68         }
69
70         /* remove upper-case vowels, starting at end */
71
72         while (orig.length() > target_length) {
73                 if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
74                         break;
75                 }
76                 orig.replace (pos, 1, "");
77         }
78
79         /* remove lower-case consonants, starting at end */
80
81         while (orig.length() > target_length) {
82                 if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
83                         break;
84                 }
85                 orig.replace (pos, 1, "");
86         }
87
88         /* remove upper-case consonants, starting at end */
89
90         while (orig.length() > target_length) {
91                 if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
92                         break;
93                 }
94                 orig.replace (pos, 1, "");
95         }
96
97         /* whatever the length is now, use it */
98         
99         return orig;
100 }
101
102 int
103 atoi (const string& s)
104 {
105         return ::atoi (s.c_str());
106 }
107
108 double
109 atof (const string& s)
110 {
111         return ::atof (s.c_str());
112 }
113
114 vector<string>
115 internationalize (const char *package_name, const char **array)
116 {
117         vector<string> v;
118
119         for (uint32_t i = 0; array[i]; ++i) {
120                 v.push_back (dgettext(package_name, array[i]));
121         }
122
123         return v;
124 }
125
126 static int32_t 
127 int_from_hex (char hic, char loc) 
128 {
129         int hi;         /* hi byte */
130         int lo;         /* low byte */
131
132         hi = (int) hic;
133
134         if( ('0'<=hi) && (hi<='9') ) {
135                 hi -= '0';
136         } else if( ('a'<= hi) && (hi<= 'f') ) {
137                 hi -= ('a'-10);
138         } else if( ('A'<=hi) && (hi<='F') ) {
139                 hi -= ('A'-10);
140         }
141         
142         lo = (int) loc;
143         
144         if( ('0'<=lo) && (lo<='9') ) {
145                 lo -= '0';
146         } else if( ('a'<=lo) && (lo<='f') ) {
147                 lo -= ('a'-10);
148         } else if( ('A'<=lo) && (lo<='F') ) {
149                 lo -= ('A'-10);
150         }
151
152         return lo + (16 * hi);
153 }
154
155 void
156 url_decode (string& url)
157 {
158         string::iterator last;
159         string::iterator next;
160
161         for (string::iterator i = url.begin(); i != url.end(); ++i) {
162                 if ((*i) == '+') {
163                         *i = ' ';
164                 }
165         }
166
167         if (url.length() <= 3) {
168                 return;
169         }
170
171         last = url.end();
172
173         --last; /* points at last char */
174         --last; /* points at last char - 1 */
175
176         for (string::iterator i = url.begin(); i != last; ) {
177
178                 if (*i == '%') {
179
180                         next = i;
181
182                         url.erase (i);
183                         
184                         i = next;
185                         ++next;
186                         
187                         if (isxdigit (*i) && isxdigit (*next)) {
188                                 /* replace first digit with char */
189                                 *i = int_from_hex (*i,*next);
190                                 ++i; /* points at 2nd of 2 digits */
191                                 url.erase (i);
192                         }
193                 } else {
194                         ++i;
195                 }
196         }
197 }
198
199 void
200 url_decode (ustring& url)
201 {
202         ustring::iterator last;
203         ustring::iterator next;
204
205         for (ustring::iterator i = url.begin(); i != url.end(); ++i) {
206                 if ((*i) == '+') {
207                         next = i;
208                         ++next;
209                         url.replace (i, next, 1, ' ');
210                 }
211         }
212
213         if (url.length() <= 3) {
214                 return;
215         }
216
217         last = url.end();
218
219         --last; /* points at last char */
220         --last; /* points at last char - 1 */
221
222         for (ustring::iterator i = url.begin(); i != last; ) {
223
224                 if (*i == '%') {
225
226                         next = i;
227
228                         url.erase (i);
229                         
230                         i = next;
231                         ++next;
232                         
233                         if (isxdigit (*i) && isxdigit (*next)) {
234                                 /* replace first digit with char */
235                                 url.replace (i, next, 1, (gunichar) int_from_hex (*i,*next));
236                                 ++i; /* points at 2nd of 2 digits */
237                                 url.erase (i);
238                         }
239                 } else {
240                         ++i;
241                 }
242         }
243 }
244
245 #if 0
246 string
247 length2string (const int32_t frames, const float sample_rate)
248 {
249     int32_t secs = (int32_t) (frames / sample_rate);
250     int32_t hrs =  secs / 3600;
251     secs -= (hrs * 3600);
252     int32_t mins = secs / 60;
253     secs -= (mins * 60);
254
255     int32_t total_secs = (hrs * 3600) + (mins * 60) + secs;
256     int32_t frames_remaining = (int) floor (frames - (total_secs * sample_rate));
257     float fractional_secs = (float) frames_remaining / sample_rate;
258
259     char duration_str[32];
260     sprintf (duration_str, "%02" PRIi32 ":%02" PRIi32 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
261
262     return duration_str;
263 }
264 #endif
265
266 string
267 length2string (const int64_t frames, const double sample_rate)
268 {
269         int64_t secs = (int64_t) floor (frames / sample_rate);
270         int64_t hrs =  secs / 3600LL;
271         secs -= (hrs * 3600LL);
272         int64_t mins = secs / 60LL;
273         secs -= (mins * 60LL);
274         
275         int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs;
276         int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate));
277         float fractional_secs = (float) frames_remaining / sample_rate;
278         
279         char duration_str[64];
280         sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
281         
282         return duration_str;
283 }
284 static bool 
285 chars_equal_ignore_case(char x, char y)
286 {
287         static std::locale loc;
288         return toupper(x, loc) == toupper(y, loc);
289 }
290
291 bool 
292 strings_equal_ignore_case (const string& a, const string& b)
293 {
294         if (a.length() == b.length()) {
295                 return std::equal (a.begin(), a.end(), b.begin(), chars_equal_ignore_case);
296         }
297         return false;
298 }
299
300
301 } // namespace PBD