1 /* Defines String::ucompose(fmt, arg...) for easy, i18n-friendly
2 * composition of strings with Gtkmm >= 1.3.* (see www.gtkmm.org).
3 * Uses Glib::ustring instead of std::string which doesn't work with
4 * Gtkmm due to character encoding troubles with stringstreams.
8 * Copyright (c) 2002, 03, 04 Ole Laursen <olau@hardworking.dk>.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this file; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 // Basic usage is like
29 // String::ucompose("This is a %1x%2 matrix.", rows, cols);
31 // See http://www.cs.aau.dk/~olau/compose/ or the included
32 // README.compose for more details.
35 #ifndef STRING_UCOMPOSE_HPP
36 #define STRING_UCOMPOSE_HPP
38 #include <glibmm/ustring.h>
39 #include <glibmm/convert.h>
44 #include <map> // for multimap
46 namespace UStringPrivate
48 // the actual composition class - using String::ucompose is cleaner, so we
53 // initialize and prepare format string on the form "text %1 text %2 etc."
54 explicit Composition(std::string fmt);
56 // supply an replacement argument starting from %1
58 Composition &arg(const T &obj);
60 // compose and return string
61 Glib::ustring str() const;
64 std::wostringstream os;
67 // we store the output as a list - when the output string is requested, the
68 // list is concatenated to a string; this way we can keep iterators into
69 // the list instead of into a string where they're possibly invalidated
70 // when inserting a specification string
71 typedef std::list<std::string> output_list;
74 // the initial parse of the format string fills in the specification map
75 // with positions for each of the various %?s
76 typedef std::multimap<int, output_list::iterator> specification_map;
77 specification_map specs;
80 std::string stringify(T obj);
83 // helper for converting spec string numbers
84 inline int char_to_int(char c)
97 default: return -1000;
101 inline bool is_number(int n)
121 template <typename T>
122 inline std::string Composition::stringify(T obj)
126 std::wstring str = os.str();
128 return Glib::convert(std::string(reinterpret_cast<const char *>(str.data()),
129 str.size() * sizeof(wchar_t)),
133 // specialisations for the common string types
136 Composition::stringify<std::string>(std::string obj)
143 Composition::stringify<Glib::ustring>(Glib::ustring obj)
150 Composition::stringify<const char *>(const char *obj)
155 // implementation of class Composition
156 template <typename T>
157 inline Composition &Composition::arg(const T &obj)
159 Glib::ustring rep = stringify(obj);
161 if (!rep.empty()) { // manipulators don't produce output
162 for (specification_map::const_iterator i = specs.lower_bound(arg_no),
163 end = specs.upper_bound(arg_no); i != end; ++i) {
164 output_list::iterator pos = i->second;
167 output.insert(pos, rep);
170 os.str(std::wstring());
178 inline Composition::Composition(std::string fmt)
182 //os.imbue(std::locale("")); // use the user's locale for the stream
184 std::string::size_type b = 0, i = 0;
186 // fill in output with the strings between the %1 %2 %3 etc. and
187 // fill in specs with the positions
188 while (i < fmt.length()) {
189 if (fmt[i] == '%' && i + 1 < fmt.length()) {
190 if (fmt[i + 1] == '%') { // catch %%
191 fmt.replace(i, 2, "%");
194 else if (is_number(fmt[i + 1])) { // aha! a spec!
196 output.push_back(fmt.substr(b, i - b));
198 int n = 1; // number of digits
202 spec_no += char_to_int(fmt[i + n]);
205 } while (i + n < fmt.length() && is_number(fmt[i + n]));
208 output_list::iterator pos = output.end();
209 --pos; // safe since we have just inserted a string
211 specs.insert(specification_map::value_type(spec_no, pos));
213 // jump over spec string
224 if (i - b > 0) // add the rest of the string
225 output.push_back(fmt.substr(b, i - b));
228 inline Glib::ustring Composition::str() const
233 for (output_list::const_iterator i = output.begin(), end = output.end();
244 // a series of functions which accept a format string on the form "text %1
245 // more %2 less %3" and a number of templated parameters and spits out the
247 template <typename T1>
248 inline Glib::ustring ucompose(const Glib::ustring &fmt, const T1 &o1)
250 UStringPrivate::Composition c(fmt);
255 template <typename T1, typename T2>
256 inline Glib::ustring ucompose(const Glib::ustring &fmt,
257 const T1 &o1, const T2 &o2)
259 UStringPrivate::Composition c(fmt);
264 template <typename T1, typename T2, typename T3>
265 inline Glib::ustring ucompose(const Glib::ustring &fmt,
266 const T1 &o1, const T2 &o2, const T3 &o3)
268 UStringPrivate::Composition c(fmt);
269 c.arg(o1).arg(o2).arg(o3);
273 template <typename T1, typename T2, typename T3, typename T4>
274 inline Glib::ustring ucompose(const Glib::ustring &fmt,
275 const T1 &o1, const T2 &o2, const T3 &o3,
278 UStringPrivate::Composition c(fmt);
279 c.arg(o1).arg(o2).arg(o3).arg(o4);
283 template <typename T1, typename T2, typename T3, typename T4, typename T5>
284 inline Glib::ustring ucompose(const Glib::ustring &fmt,
285 const T1 &o1, const T2 &o2, const T3 &o3,
286 const T4 &o4, const T5 &o5)
288 UStringPrivate::Composition c(fmt);
289 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
293 template <typename T1, typename T2, typename T3, typename T4, typename T5,
295 inline Glib::ustring ucompose(const Glib::ustring &fmt,
296 const T1 &o1, const T2 &o2, const T3 &o3,
297 const T4 &o4, const T5 &o5, const T6 &o6)
299 UStringPrivate::Composition c(fmt);
300 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
304 template <typename T1, typename T2, typename T3, typename T4, typename T5,
305 typename T6, typename T7>
306 inline Glib::ustring ucompose(const Glib::ustring &fmt,
307 const T1 &o1, const T2 &o2, const T3 &o3,
308 const T4 &o4, const T5 &o5, const T6 &o6,
311 UStringPrivate::Composition c(fmt);
312 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
316 template <typename T1, typename T2, typename T3, typename T4, typename T5,
317 typename T6, typename T7, typename T8>
318 inline Glib::ustring ucompose(const Glib::ustring &fmt,
319 const T1 &o1, const T2 &o2, const T3 &o3,
320 const T4 &o4, const T5 &o5, const T6 &o6,
321 const T7 &o7, const T8 &o8)
323 UStringPrivate::Composition c(fmt);
324 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
328 template <typename T1, typename T2, typename T3, typename T4, typename T5,
329 typename T6, typename T7, typename T8, typename T9>
330 inline Glib::ustring ucompose(const Glib::ustring &fmt,
331 const T1 &o1, const T2 &o2, const T3 &o3,
332 const T4 &o4, const T5 &o5, const T6 &o6,
333 const T7 &o7, const T8 &o8, const T9 &o9)
335 UStringPrivate::Composition c(fmt);
336 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
340 template <typename T1, typename T2, typename T3, typename T4, typename T5,
341 typename T6, typename T7, typename T8, typename T9, typename T10>
342 inline Glib::ustring ucompose(const Glib::ustring &fmt,
343 const T1 &o1, const T2 &o2, const T3 &o3,
344 const T4 &o4, const T5 &o5, const T6 &o6,
345 const T7 &o7, const T8 &o8, const T9 &o9,
348 UStringPrivate::Composition c(fmt);
349 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
354 template <typename T1, typename T2, typename T3, typename T4, typename T5,
355 typename T6, typename T7, typename T8, typename T9, typename T10,
357 inline Glib::ustring ucompose(const Glib::ustring &fmt,
358 const T1 &o1, const T2 &o2, const T3 &o3,
359 const T4 &o4, const T5 &o5, const T6 &o6,
360 const T7 &o7, const T8 &o8, const T9 &o9,
361 const T10 &o10, const T11 &o11)
363 UStringPrivate::Composition c(fmt);
364 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
369 template <typename T1, typename T2, typename T3, typename T4, typename T5,
370 typename T6, typename T7, typename T8, typename T9, typename T10,
371 typename T11, typename T12>
372 inline Glib::ustring ucompose(const Glib::ustring &fmt,
373 const T1 &o1, const T2 &o2, const T3 &o3,
374 const T4 &o4, const T5 &o5, const T6 &o6,
375 const T7 &o7, const T8 &o8, const T9 &o9,
376 const T10 &o10, const T11 &o11, const T12 &o12)
378 UStringPrivate::Composition c(fmt);
379 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
380 .arg(o10).arg(o11).arg(o12);
384 template <typename T1, typename T2, typename T3, typename T4, typename T5,
385 typename T6, typename T7, typename T8, typename T9, typename T10,
386 typename T11, typename T12, typename T13>
387 inline Glib::ustring ucompose(const Glib::ustring &fmt,
388 const T1 &o1, const T2 &o2, const T3 &o3,
389 const T4 &o4, const T5 &o5, const T6 &o6,
390 const T7 &o7, const T8 &o8, const T9 &o9,
391 const T10 &o10, const T11 &o11, const T12 &o12,
394 UStringPrivate::Composition c(fmt);
395 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
396 .arg(o10).arg(o11).arg(o12).arg(o13);
400 template <typename T1, typename T2, typename T3, typename T4, typename T5,
401 typename T6, typename T7, typename T8, typename T9, typename T10,
402 typename T11, typename T12, typename T13, typename T14>
403 inline Glib::ustring ucompose(const Glib::ustring &fmt,
404 const T1 &o1, const T2 &o2, const T3 &o3,
405 const T4 &o4, const T5 &o5, const T6 &o6,
406 const T7 &o7, const T8 &o8, const T9 &o9,
407 const T10 &o10, const T11 &o11, const T12 &o12,
408 const T13 &o13, const T14 &o14)
410 UStringPrivate::Composition c(fmt);
411 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
412 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
416 template <typename T1, typename T2, typename T3, typename T4, typename T5,
417 typename T6, typename T7, typename T8, typename T9, typename T10,
418 typename T11, typename T12, typename T13, typename T14,
420 inline Glib::ustring ucompose(const Glib::ustring &fmt,
421 const T1 &o1, const T2 &o2, const T3 &o3,
422 const T4 &o4, const T5 &o5, const T6 &o6,
423 const T7 &o7, const T8 &o8, const T9 &o9,
424 const T10 &o10, const T11 &o11, const T12 &o12,
425 const T13 &o13, const T14 &o14, const T15 &o15)
427 UStringPrivate::Composition c(fmt);
428 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
429 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
435 #endif // STRING_UCOMPOSE_HPP