More build fixes.
[dcpomatic.git] / src / lib / compose.hpp
index aa67b5a1fd8bc9f1027ab272b20c93ff744d8732..2d22947178703a71deb702e3faedeb6fbd129ca2 100644 (file)
@@ -1,4 +1,5 @@
-/* Defines String::compose(fmt, arg...) for easy, i18n-friendly
+/* -*- c-basic-offset: 2 -*-
+ * Defines String::compose(fmt, arg...) for easy, i18n-friendly
  * composition of strings.
  *
  * Version 1.0.
 #ifndef STRING_COMPOSE_H
 #define STRING_COMPOSE_H
 
+#include <boost/filesystem.hpp>
 #include <string>
 #include <list>
-#include <map>                 // for multimap
-#include "safe_stringstream.h"
+#include <map>
+#include <inttypes.h>
+#include <cstdio>
 
 namespace StringPrivate
 {
@@ -56,7 +59,7 @@ namespace StringPrivate
     std::string str() const;
 
   private:
-    SafeStringStream os;
+    std::string os;
     int arg_no;
 
     // we store the output as a list - when the output string is requested, the
@@ -104,35 +107,119 @@ namespace StringPrivate
     case '8':
     case '9':
       return true;
-    
+
     default:
       return false;
     }
   }
 
+  template <typename T>
+  inline void write(std::string& s, const T& obj)
+  {
+    /* Assume anything not specialized has a to_string() method */
+    s += to_string (obj);
+  }
+
+  template <>
+  inline void write(std::string& s, const int64_t& obj)
+  {
+    char buffer[64];
+#ifdef DCPOMATIC_WINDOWS
+    __mingw_snprintf(buffer, 64, "%" PRId64, obj);
+#else
+    snprintf(buffer, 64, "%" PRId64, obj);
+#endif
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, const int& obj)
+  {
+    char buffer[64];
+    snprintf(buffer, 64, "%d", obj);
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, const unsigned int& obj)
+  {
+    char buffer[64];
+    snprintf(buffer, 64, "%ud", obj);
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, const long unsigned int& obj)
+  {
+    char buffer[64];
+    snprintf(buffer, 64, "%lu", obj);
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, const float& obj)
+  {
+    char buffer[64];
+    snprintf(buffer, 64, "%f", obj);
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, const char& obj)
+  {
+    s += obj;
+  }
+
+  template <>
+  inline void write(std::string& s, const double& obj)
+  {
+    char buffer[64];
+    snprintf(buffer, 64, "%f", obj);
+    s += buffer;
+  }
+
+  template <>
+  inline void write(std::string& s, char const * const & obj)
+  {
+    s += obj;
+  }
+
+  template <>
+  inline void write(std::string& s, char* const & obj)
+  {
+    s += obj;
+  }
+
+  template <>
+  inline void write(std::string& s, const std::string& obj)
+  {
+    s += obj;
+  }
+
+  template <>
+  inline void write(std::string& s, const boost::filesystem::path & obj)
+  {
+    s += obj.string();
+  }
 
   // implementation of class Composition
   template <typename T>
   inline Composition &Composition::arg(const T &obj)
   {
-    os << obj;
+    write(os, obj);
 
-    std::string rep = os.str();
-  
-    if (!rep.empty()) {                // manipulators don't produce output
-      for (specification_map::const_iterator i = specs.lower_bound(arg_no),
-            end = specs.upper_bound(arg_no); i != end; ++i) {
+    if (!os.empty()) {         // manipulators don't produce output
+      for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
        output_list::iterator pos = i->second;
        ++pos;
-      
-       output.insert(pos, rep);
+
+       output.insert(pos, os);
       }
-    
-      os.str(std::string());
-      //os.clear();
+
+      os = "";
       ++arg_no;
     }
-  
+
     return *this;
   }
 
@@ -140,7 +227,7 @@ namespace StringPrivate
     : arg_no(1)
   {
     std::string::size_type b = 0, i = 0;
-  
+
     // fill in output with the strings between the %1 %2 %3 etc. and
     // fill in specs with the positions
     while (i < fmt.length()) {
@@ -152,7 +239,7 @@ namespace StringPrivate
        else if (is_number(fmt[i + 1])) { // aha! a spec!
          // save string
          output.push_back(fmt.substr(b, i - b));
-       
+
          int n = 1;            // number of digits
          int spec_no = 0;
 
@@ -165,9 +252,9 @@ namespace StringPrivate
          spec_no /= 10;
          output_list::iterator pos = output.end();
          --pos;                // safe since we have just inserted a string>
-       
+
          specs.insert(specification_map::value_type(spec_no, pos));
-       
+
          // jump over spec string
          i += n;
          b = i;
@@ -178,7 +265,7 @@ namespace StringPrivate
       else
        ++i;
     }
-  
+
     if (i - b > 0)             // add the rest of the string
       output.push_back(fmt.substr(b, i - b));
   }
@@ -187,17 +274,17 @@ namespace StringPrivate
   {
     // assemble string
     std::string str;
-  
+
     for (output_list::const_iterator i = output.begin(), end = output.end();
         i != end; ++i)
       str += *i;
-  
+
     return str;
   }
 }
 
 // now for the real thing(s)
-namespace String 
+namespace String
 {
   // a series of functions which accept a format string on the form "text %1
   // more %2 less %3" and a number of templated parameters and spits out the
@@ -308,7 +395,7 @@ namespace String
       .arg(o10);
     return c.str();
   }
-  
+
   template <typename T1, typename T2, typename T3, typename T4, typename T5,
            typename T6, typename T7, typename T8, typename T9, typename T10,
            typename T11>