initial import
This commit is contained in:
parent
04e770ff17
commit
d06d10b181
|
@ -0,0 +1,435 @@
|
|||
/* Defines String::ucompose(fmt, arg...) for easy, i18n-friendly
|
||||
* composition of strings with Gtkmm >= 1.3.* (see www.gtkmm.org).
|
||||
* Uses Glib::ustring instead of std::string which doesn't work with
|
||||
* Gtkmm due to character encoding troubles with stringstreams.
|
||||
*
|
||||
* Version 1.0.4.
|
||||
*
|
||||
* Copyright (c) 2002, 03, 04 Ole Laursen <olau@hardworking.dk>.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
|
||||
//
|
||||
// Basic usage is like
|
||||
//
|
||||
// String::ucompose("This is a %1x%2 matrix.", rows, cols);
|
||||
//
|
||||
// See http://www.cs.aau.dk/~olau/compose/ or the included
|
||||
// README.compose for more details.
|
||||
//
|
||||
|
||||
#ifndef STRING_UCOMPOSE_HPP
|
||||
#define STRING_UCOMPOSE_HPP
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
#include <glibmm/convert.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map> // for multimap
|
||||
|
||||
namespace UStringPrivate
|
||||
{
|
||||
// the actual composition class - using String::ucompose is cleaner, so we
|
||||
// hide it here
|
||||
class Composition
|
||||
{
|
||||
public:
|
||||
// initialize and prepare format string on the form "text %1 text %2 etc."
|
||||
explicit Composition(std::string fmt);
|
||||
|
||||
// supply an replacement argument starting from %1
|
||||
template <typename T>
|
||||
Composition &arg(const T &obj);
|
||||
|
||||
// compose and return string
|
||||
Glib::ustring str() const;
|
||||
|
||||
private:
|
||||
std::wostringstream os;
|
||||
int arg_no;
|
||||
|
||||
// we store the output as a list - when the output string is requested, the
|
||||
// list is concatenated to a string; this way we can keep iterators into
|
||||
// the list instead of into a string where they're possibly invalidated
|
||||
// when inserting a specification string
|
||||
typedef std::list<std::string> output_list;
|
||||
output_list output;
|
||||
|
||||
// the initial parse of the format string fills in the specification map
|
||||
// with positions for each of the various %?s
|
||||
typedef std::multimap<int, output_list::iterator> specification_map;
|
||||
specification_map specs;
|
||||
|
||||
template <typename T>
|
||||
std::string stringify(T obj);
|
||||
};
|
||||
|
||||
// helper for converting spec string numbers
|
||||
inline int char_to_int(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case '0': return 0;
|
||||
case '1': return 1;
|
||||
case '2': return 2;
|
||||
case '3': return 3;
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
default: return -1000;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_number(int n)
|
||||
{
|
||||
switch (n) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string Composition::stringify(T obj)
|
||||
{
|
||||
os << obj;
|
||||
|
||||
std::wstring str = os.str();
|
||||
|
||||
return Glib::convert(std::string(reinterpret_cast<const char *>(str.data()),
|
||||
str.size() * sizeof(wchar_t)),
|
||||
"UTF-8", "WCHAR_T");
|
||||
}
|
||||
|
||||
// specialisations for the common string types
|
||||
template <>
|
||||
inline std::string
|
||||
Composition::stringify<std::string>(std::string obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string
|
||||
Composition::stringify<Glib::ustring>(Glib::ustring obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string
|
||||
Composition::stringify<const char *>(const char *obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
// implementation of class Composition
|
||||
template <typename T>
|
||||
inline Composition &Composition::arg(const T &obj)
|
||||
{
|
||||
Glib::ustring rep = stringify(obj);
|
||||
|
||||
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) {
|
||||
output_list::iterator pos = i->second;
|
||||
++pos;
|
||||
|
||||
output.insert(pos, rep);
|
||||
}
|
||||
|
||||
os.str(std::wstring());
|
||||
//os.clear();
|
||||
++arg_no;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Composition::Composition(std::string fmt)
|
||||
: arg_no(1)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
os.imbue(std::locale("")); // use the user's locale for the stream
|
||||
#endif
|
||||
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()) {
|
||||
if (fmt[i] == '%' && i + 1 < fmt.length()) {
|
||||
if (fmt[i + 1] == '%') { // catch %%
|
||||
fmt.replace(i, 2, "%");
|
||||
++i;
|
||||
}
|
||||
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;
|
||||
|
||||
do {
|
||||
spec_no += char_to_int(fmt[i + n]);
|
||||
spec_no *= 10;
|
||||
++n;
|
||||
} while (i + n < fmt.length() && is_number(fmt[i + n]));
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i - b > 0) // add the rest of the string
|
||||
output.push_back(fmt.substr(b, i - b));
|
||||
}
|
||||
|
||||
inline Glib::ustring Composition::str() const
|
||||
{
|
||||
// assemble string
|
||||
std::string str;
|
||||
|
||||
for (output_list::const_iterator i = output.begin(), end = output.end();
|
||||
i != end; ++i)
|
||||
str += *i;
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
// composited string
|
||||
template <typename T1>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt, const T1 &o1)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
|
||||
return c.str();
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.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>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10, const T11 &o11)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.arg(o10).arg(o11);
|
||||
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, typename T12>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10, const T11 &o11, const T12 &o12)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.arg(o10).arg(o11).arg(o12);
|
||||
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, typename T12, typename T13>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10, const T11 &o11, const T12 &o12,
|
||||
const T13 &o13)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.arg(o10).arg(o11).arg(o12).arg(o13);
|
||||
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, typename T12, typename T13, typename T14>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10, const T11 &o11, const T12 &o12,
|
||||
const T13 &o13, const T14 &o14)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
|
||||
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, typename T12, typename T13, typename T14,
|
||||
typename T15>
|
||||
inline Glib::ustring ucompose(const Glib::ustring &fmt,
|
||||
const T1 &o1, const T2 &o2, const T3 &o3,
|
||||
const T4 &o4, const T5 &o5, const T6 &o6,
|
||||
const T7 &o7, const T8 &o8, const T9 &o9,
|
||||
const T10 &o10, const T11 &o11, const T12 &o12,
|
||||
const T13 &o13, const T14 &o14, const T15 &o15)
|
||||
{
|
||||
UStringPrivate::Composition c(fmt);
|
||||
c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
|
||||
.arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
|
||||
return c.str();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // STRING_UCOMPOSE_HPP
|
Loading…
Reference in New Issue