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