// -*- indent-tabs-mode: nil -*- #ifndef __ARC_ISTRING__ #define __ARC_ISTRING__ #include #include #include #include #include #include // snprintf #include // free #include // strcpy, strdup #define istring(x) (x) namespace Arc { /** \cond Class used internally by IString. */ class PrintFBase { public: PrintFBase(); virtual ~PrintFBase(); virtual void msg(std::ostream& os) const = 0; virtual void msg(std::string& s) const = 0; void Retain(); bool Release(); private: // Copying not allowed PrintFBase(const PrintFBase&); // Assignment not allowed PrintFBase& operator=(const PrintFBase&); int refcount; }; /** \endcond */ /// Return the translation of the given string. /** \ingroup common */ const char* FindTrans(const char *p); /// Return the plural form translation of the given string when it refers to multiple n. /** \ingroup common */ const char* FindNTrans(const char *s, const char *p, unsigned long n); /** \cond Class used internally by IString. */ template class PrintF : public PrintFBase { public: PrintF(const std::string& m, const T0& tt0 = 0, const T1& tt1 = 0, const T2& tt2 = 0, const T3& tt3 = 0, const T4& tt4 = 0, const T5& tt5 = 0, const T6& tt6 = 0, const T7& tt7 = 0) : PrintFBase(), m(m) { Copy(t0, tt0); Copy(t1, tt1); Copy(t2, tt2); Copy(t3, tt3); Copy(t4, tt4); Copy(t5, tt5); Copy(t6, tt6); Copy(t7, tt7); } ~PrintF() { for (std::list::iterator it = ptrs.begin(); it != ptrs.end(); it++) free(*it); } virtual void msg(std::ostream& os) const { char buffer[2048]; snprintf(buffer, 2048, Get(m), Get(t0), Get(t1), Get(t2), Get(t3), Get(t4), Get(t5), Get(t6), Get(t7)); os << buffer; } virtual void msg(std::string& s) const { char buffer[2048]; snprintf(buffer, 2048, Get(m), Get(t0), Get(t1), Get(t2), Get(t3), Get(t4), Get(t5), Get(t6), Get(t7)); s = buffer; } private: // general case template inline void Copy(T& t, const U& u) { t = u; } // char[] and const char[] template inline void Copy(T& t, const char u[]) { strcpy(t, u); } // const char* inline void Copy(const char*& t, const char*const& u) { t = strdup(u); ptrs.push_back(const_cast(t)); } // char* inline void Copy(char*& t, char*const& u) { t = strdup(u); ptrs.push_back(t); } // general case template inline static const T& Get(const T& t) { return t; } // const char[] and const char* inline static const char* Get(const char*const& t) { return FindTrans(t); } // char[] and char* inline static const char* Get(char*const& t) { return FindTrans(const_cast(t)); } // std::string inline static const char* Get(const std::string& t) { return FindTrans(t.c_str()); } // std::string ()() inline static const char* Get(std::string (*t)()) { return FindTrans(t().c_str()); } // Glib::ustring inline static const char* Get(const Glib::ustring& t) { return FindTrans(t.c_str()); } // Glib::ustring ()() inline static const char* Get(Glib::ustring (*t)()) { return FindTrans(t().c_str()); } // sigc::slot* inline static const char* Get(const sigc::slot *t) { return (*t)(); } std::string m; T0 t0; T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; std::list ptrs; }; /** \endcond */ /// Class used for localised output of log messages. /** IString should only be used directly in rare cases. Logger should be used * instead in most cases. * \ingroup common * \headerfile IString.h arc/IString.h */ class IString { public: IString(const std::string& m) : p(new PrintF<>(m)) {} template IString(const std::string& m, const T0& t0) : p(new PrintF(m, t0)) {} template IString(const std::string& m, const T0& t0, const T1& t1) : p(new PrintF(m, t0, t1)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2) : p(new PrintF(m, t0, t1, t2)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2, const T3& t3) : p(new PrintF(m, t0, t1, t2, t3)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) : p(new PrintF(m, t0, t1, t2, t3, t4)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) : p(new PrintF(m, t0, t1, t2, t3, t4, t5)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) : p(new PrintF(m, t0, t1, t2, t3, t4, t5, t6)) {} template IString(const std::string& m, const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) : p(new PrintF(m, t0, t1, t2, t3, t4, t5, t6, t7)) {} ~IString(); IString(const IString& istr); IString& operator=(const IString& istr); std::string str(void) const; private: PrintFBase *p; friend std::ostream& operator<<(std::ostream& os, const IString& msg); }; /// Output localised message to an output stream. std::ostream& operator<<(std::ostream& os, const IString& msg); } // namespace Arc #endif // __ARC_ISTRING__