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