enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / pbd / convert.cc
index 832c54acd84c186eb1cc21b55c01b87ee51cb2f3..dd43475e6973583cc147feadc749be218afba673 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2006 Paul Davis 
+    Copyright (C) 2006 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 */
 
 #include <cmath>
+#include <algorithm>
+#include <string>
+
 #include <stdint.h>
+#include <stdlib.h>
+#include <cstdio>
+#include <ctype.h>
+#include <cstring>
 #ifndef __STDC_FORMAT_MACROS
 #define __STDC_FORMAT_MACROS
 #endif
 #include <inttypes.h>
 
+#include <glib.h>
+
 #include "pbd/convert.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using std::string;
 using std::vector;
+using Glib::ustring;
 
 namespace PBD {
 
+string
+capitalize (const string& str)
+{
+        string ret = str;
+        if (!str.empty()) {
+                /* XXX not unicode safe */
+                ret[0] = toupper (str[0]);
+        }
+        return ret;
+}
+
+string
+downcase (const string& str)
+{
+       string copy (str);
+       std::transform (copy.begin(), copy.end(), copy.begin(), ::tolower);
+       return copy;
+}
+
+const char*
+downcase (const char* str)
+{
+       char *copy = strdup (str);
+       for (char* p = copy; *p; ++p) {
+               *p = tolower (*p);
+       }
+       return copy;
+}
+
 string
 short_version (string orig, string::size_type target_length)
 {
@@ -93,20 +132,32 @@ short_version (string orig, string::size_type target_length)
        }
 
        /* whatever the length is now, use it */
-       
+
        return orig;
 }
 
 int
 atoi (const string& s)
 {
-       return std::atoi (s.c_str());
+       return ::atoi (s.c_str());
+}
+
+int32_t
+atol (const string& s)
+{
+       return (int32_t) ::atol (s.c_str());
+}
+
+int64_t
+atoll (const string& s)
+{
+       return (int64_t) ::atoll (s.c_str());
 }
 
 double
 atof (const string& s)
 {
-       return std::atof (s.c_str());
+       return ::atof (s.c_str());
 }
 
 vector<string>
@@ -121,8 +172,8 @@ internationalize (const char *package_name, const char **array)
        return v;
 }
 
-static int32_t 
-int_from_hex (char hic, char loc) 
+static int32_t
+int_from_hex (char hic, char loc)
 {
        int hi;         /* hi byte */
        int lo;         /* low byte */
@@ -136,9 +187,9 @@ int_from_hex (char hic, char loc)
        } else if( ('A'<=hi) && (hi<='F') ) {
                hi -= ('A'-10);
        }
-       
+
        lo = (int) loc;
-       
+
        if( ('0'<=lo) && (lo<='9') ) {
                lo -= '0';
        } else if( ('a'<=lo) && (lo<='f') ) {
@@ -150,48 +201,23 @@ int_from_hex (char hic, char loc)
        return lo + (16 * hi);
 }
 
-void
-url_decode (string& url)
+string
+url_decode (string const & url)
 {
-       string::iterator last;
-       string::iterator next;
-
-       for (string::iterator i = url.begin(); i != url.end(); ++i) {
-               if ((*i) == '+') {
-                       *i = ' ';
-               }
-       }
-
-       if (url.length() <= 3) {
-               return;
-       }
-
-       last = url.end();
-
-       --last; /* points at last char */
-       --last; /* points at last char - 1 */
-
-       for (string::iterator i = url.begin(); i != last; ) {
-
-               if (*i == '%') {
-
-                       next = i;
-
-                       url.erase (i);
-                       
-                       i = next;
-                       ++next;
-                       
-                       if (isxdigit (*i) && isxdigit (*next)) {
-                               /* replace first digit with char */
-                               *i = int_from_hex (*i,*next);
-                               ++i; /* points at 2nd of 2 digits */
-                               url.erase (i);
-                       }
+       string decoded;
+
+       for (string::size_type i = 0; i < url.length(); ++i) {
+               if (url[i] == '+') {
+                       decoded += ' ';
+               } else if (url[i] == '%' && i <= url.length() - 3) {
+                       decoded += char (int_from_hex (url[i + 1], url[i + 2]));
+                       i += 2;
                } else {
-                       ++i;
+                       decoded += url[i];
                }
        }
+
+       return decoded;
 }
 
 #if 0
@@ -223,15 +249,71 @@ length2string (const int64_t frames, const double sample_rate)
        secs -= (hrs * 3600LL);
        int64_t mins = secs / 60LL;
        secs -= (mins * 60LL);
-       
+
        int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs;
        int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate));
        float fractional_secs = (float) frames_remaining / sample_rate;
-       
+
        char duration_str[64];
        sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
-       
+
        return duration_str;
 }
 
+static bool
+chars_equal_ignore_case(char x, char y)
+{
+       /* app should have called setlocale() if its wants this comparison to be
+          locale sensitive.
+       */
+       return toupper (x) == toupper (y);
+}
+
+bool
+strings_equal_ignore_case (const string& a, const string& b)
+{
+       if (a.length() == b.length()) {
+               return std::equal (a.begin(), a.end(), b.begin(), chars_equal_ignore_case);
+       }
+       return false;
+}
+
+bool
+string_is_affirmative (const std::string& str)
+{
+       /* to be used only with XML data - not intended to handle user input */
+
+       if (str.empty ()) {
+               return false;
+       }
+
+       /* the use of g_ascii_strncasecmp() is solely to get around issues with
+        * charsets posed by trying to use C++ for the same
+        * comparison. switching a std::string to its lower- or upper-case
+        * version has several issues, but handled by default
+        * in the way we desire when doing it in C.
+        */
+
+       return str == "1" || str == "y" || str == "Y" || (!g_ascii_strncasecmp(str.c_str(), "yes", str.length())) ||
+               (!g_ascii_strncasecmp(str.c_str(), "true", str.length()));
+}
+
+/** A wrapper for dgettext that takes a msgid of the form Context|Text.
+ *  If Context|Text is translated, the translation is returned, otherwise
+ *  just Text is returned.  Useful for getting translations of words or phrases
+ *  that have different meanings in different contexts.
+ */
+const char *
+sgettext (const char* domain_name, const char* msgid)
+{
+       const char * msgval = dgettext (domain_name, msgid);
+       if (msgval == msgid) {
+               const char * p = strrchr (msgid, '|');
+               if (p) {
+                       msgval = p + 1;
+               }
+       }
+       return msgval;
+}
+
 } // namespace PBD