Merged with trunk R1141
[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
34 namespace PBD {
35
36 string
37 short_version (string orig, string::size_type target_length)
38 {
39         /* this tries to create a recognizable abbreviation
40            of "orig" by removing characters until we meet
41            a certain target length.
42
43            note that we deliberately leave digits in the result
44            without modification.
45         */
46
47
48         string::size_type pos;
49
50         /* remove white-space and punctuation, starting at end */
51
52         while (orig.length() > target_length) {
53                 if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
54                         break;
55                 }
56                 orig.replace (pos, 1, "");
57         }
58
59         /* remove lower-case vowels, starting at end */
60
61         while (orig.length() > target_length) {
62                 if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
63                         break;
64                 }
65                 orig.replace (pos, 1, "");
66         }
67
68         /* remove upper-case vowels, starting at end */
69
70         while (orig.length() > target_length) {
71                 if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
72                         break;
73                 }
74                 orig.replace (pos, 1, "");
75         }
76
77         /* remove lower-case consonants, starting at end */
78
79         while (orig.length() > target_length) {
80                 if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
81                         break;
82                 }
83                 orig.replace (pos, 1, "");
84         }
85
86         /* remove upper-case consonants, starting at end */
87
88         while (orig.length() > target_length) {
89                 if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
90                         break;
91                 }
92                 orig.replace (pos, 1, "");
93         }
94
95         /* whatever the length is now, use it */
96         
97         return orig;
98 }
99
100 int
101 atoi (const string& s)
102 {
103         return std::atoi (s.c_str());
104 }
105
106 double
107 atof (const string& s)
108 {
109         return std::atof (s.c_str());
110 }
111
112 vector<string>
113 internationalize (const char *package_name, const char **array)
114 {
115         vector<string> v;
116
117         for (uint32_t i = 0; array[i]; ++i) {
118                 v.push_back (dgettext(package_name, array[i]));
119         }
120
121         return v;
122 }
123
124 static int32_t 
125 int_from_hex (char hic, char loc) 
126 {
127         int hi;         /* hi byte */
128         int lo;         /* low byte */
129
130         hi = (int) hic;
131
132         if( ('0'<=hi) && (hi<='9') ) {
133                 hi -= '0';
134         } else if( ('a'<= hi) && (hi<= 'f') ) {
135                 hi -= ('a'-10);
136         } else if( ('A'<=hi) && (hi<='F') ) {
137                 hi -= ('A'-10);
138         }
139         
140         lo = (int) loc;
141         
142         if( ('0'<=lo) && (lo<='9') ) {
143                 lo -= '0';
144         } else if( ('a'<=lo) && (lo<='f') ) {
145                 lo -= ('a'-10);
146         } else if( ('A'<=lo) && (lo<='F') ) {
147                 lo -= ('A'-10);
148         }
149
150         return lo + (16 * hi);
151 }
152
153 void
154 url_decode (string& url)
155 {
156         string::iterator last;
157         string::iterator next;
158
159         for (string::iterator i = url.begin(); i != url.end(); ++i) {
160                 if ((*i) == '+') {
161                         *i = ' ';
162                 }
163         }
164
165         if (url.length() <= 3) {
166                 return;
167         }
168
169         last = url.end();
170
171         --last; /* points at last char */
172         --last; /* points at last char - 1 */
173
174         for (string::iterator i = url.begin(); i != last; ) {
175
176                 if (*i == '%') {
177
178                         next = i;
179
180                         url.erase (i);
181                         
182                         i = next;
183                         ++next;
184                         
185                         if (isxdigit (*i) && isxdigit (*next)) {
186                                 /* replace first digit with char */
187                                 *i = int_from_hex (*i,*next);
188                                 ++i; /* points at 2nd of 2 digits */
189                                 url.erase (i);
190                         }
191                 } else {
192                         ++i;
193                 }
194         }
195 }
196
197 #if 0
198 string
199 length2string (const int32_t frames, const float sample_rate)
200 {
201     int32_t secs = (int32_t) (frames / sample_rate);
202     int32_t hrs =  secs / 3600;
203     secs -= (hrs * 3600);
204     int32_t mins = secs / 60;
205     secs -= (mins * 60);
206
207     int32_t total_secs = (hrs * 3600) + (mins * 60) + secs;
208     int32_t frames_remaining = (int) floor (frames - (total_secs * sample_rate));
209     float fractional_secs = (float) frames_remaining / sample_rate;
210
211     char duration_str[32];
212     sprintf (duration_str, "%02" PRIi32 ":%02" PRIi32 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
213
214     return duration_str;
215 }
216 #endif
217
218 string
219 length2string (const int64_t frames, const double sample_rate)
220 {
221         int64_t secs = (int64_t) floor (frames / sample_rate);
222         int64_t hrs =  secs / 3600LL;
223         secs -= (hrs * 3600LL);
224         int64_t mins = secs / 60LL;
225         secs -= (mins * 60LL);
226         
227         int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs;
228         int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate));
229         float fractional_secs = (float) frames_remaining / sample_rate;
230         
231         char duration_str[64];
232         sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
233         
234         return duration_str;
235 }
236
237 } // namespace PBD