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