1 /* -*- c-basic-offset: 2 -*-
2 * Defines String::compose(fmt, arg...) for easy, i18n-friendly
3 * composition of strings.
7 * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 // Basic usage is like
28 // std::cout << String::compose("This is a %1x%2 matrix.", rows, cols);
30 // See http://www.cs.aau.dk/~olau/compose/ or the included README.compose for
34 #ifndef STRING_COMPOSE_H
35 #define STRING_COMPOSE_H
37 #include "locale_convert.h"
38 #include <boost/filesystem.hpp>
47 namespace StringPrivate
49 // the actual composition class - using string::compose is cleaner, so we
54 // initialize and prepare format string on the form "text %1 text %2 etc."
55 explicit Composition(std::string fmt);
57 // supply an replacement argument starting from %1
59 Composition &arg(const T &obj);
61 // compose and return string
62 std::string str() const;
68 // we store the output as a list - when the output string is requested, the
69 // list is concatenated to a string; this way we can keep iterators into
70 // the list instead of into a string where they're possibly invalidated on
71 // inserting a specification string
72 typedef std::list<std::string> output_list;
75 // the initial parse of the format string fills in the specification map
76 // with positions for each of the various %?s
77 typedef std::multimap<int, output_list::iterator> specification_map;
78 specification_map specs;
81 // helper for converting spec string numbers
82 inline int char_to_int(char c)
95 default: return -1000;
99 inline bool is_number(int n)
119 // implementation of class Composition
120 template <typename T>
121 inline Composition &Composition::arg(const T &obj)
123 os += dcp::locale_convert<std::string> (obj);
125 if (!os.empty()) { // manipulators don't produce output
126 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
127 output_list::iterator pos = i->second;
130 output.insert(pos, os);
140 inline Composition::Composition(std::string fmt)
143 std::string::size_type b = 0, i = 0;
145 // fill in output with the strings between the %1 %2 %3 etc. and
146 // fill in specs with the positions
147 while (i < fmt.length()) {
148 if (fmt[i] == '%' && i + 1 < fmt.length()) {
149 if (fmt[i + 1] == '%') { // catch %%
150 fmt.replace(i, 2, "%");
153 else if (is_number(fmt[i + 1])) { // aha! a spec!
155 output.push_back(fmt.substr(b, i - b));
157 int n = 1; // number of digits
161 spec_no += char_to_int(fmt[i + n]);
164 } while (i + n < fmt.length() && is_number(fmt[i + n]));
167 output_list::iterator pos = output.end();
168 --pos; // safe since we have just inserted a string>
170 specs.insert(specification_map::value_type(spec_no, pos));
172 // jump over spec string
183 if (i - b > 0) // add the rest of the string
184 output.push_back(fmt.substr(b, i - b));
187 inline std::string Composition::str() const
192 for (output_list::const_iterator i = output.begin(), end = output.end();
200 // now for the real thing(s)
203 // a series of functions which accept a format string on the form "text %1
204 // more %2 less %3" and a number of templated parameters and spits out the
206 template <typename T1>
207 inline std::string compose(const std::string &fmt, const T1 &o1)
209 StringPrivate::Composition c(fmt);
214 template <typename T1, typename T2>
215 inline std::string compose(const std::string &fmt,
216 const T1 &o1, const T2 &o2)
218 StringPrivate::Composition c(fmt);
223 template <typename T1, typename T2, typename T3>
224 inline std::string compose(const std::string &fmt,
225 const T1 &o1, const T2 &o2, const T3 &o3)
227 StringPrivate::Composition c(fmt);
228 c.arg(o1).arg(o2).arg(o3);
232 template <typename T1, typename T2, typename T3, typename T4>
233 inline std::string compose(const std::string &fmt,
234 const T1 &o1, const T2 &o2, const T3 &o3,
237 StringPrivate::Composition c(fmt);
238 c.arg(o1).arg(o2).arg(o3).arg(o4);
242 template <typename T1, typename T2, typename T3, typename T4, typename T5>
243 inline std::string compose(const std::string &fmt,
244 const T1 &o1, const T2 &o2, const T3 &o3,
245 const T4 &o4, const T5 &o5)
247 StringPrivate::Composition c(fmt);
248 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
252 template <typename T1, typename T2, typename T3, typename T4, typename T5,
254 inline std::string compose(const std::string &fmt,
255 const T1 &o1, const T2 &o2, const T3 &o3,
256 const T4 &o4, const T5 &o5, const T6 &o6)
258 StringPrivate::Composition c(fmt);
259 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
263 template <typename T1, typename T2, typename T3, typename T4, typename T5,
264 typename T6, typename T7>
265 inline std::string compose(const std::string &fmt,
266 const T1 &o1, const T2 &o2, const T3 &o3,
267 const T4 &o4, const T5 &o5, const T6 &o6,
270 StringPrivate::Composition c(fmt);
271 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
275 template <typename T1, typename T2, typename T3, typename T4, typename T5,
276 typename T6, typename T7, typename T8>
277 inline std::string compose(const std::string &fmt,
278 const T1 &o1, const T2 &o2, const T3 &o3,
279 const T4 &o4, const T5 &o5, const T6 &o6,
280 const T7 &o7, const T8 &o8)
282 StringPrivate::Composition c(fmt);
283 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
287 template <typename T1, typename T2, typename T3, typename T4, typename T5,
288 typename T6, typename T7, typename T8, typename T9>
289 inline std::string compose(const std::string &fmt,
290 const T1 &o1, const T2 &o2, const T3 &o3,
291 const T4 &o4, const T5 &o5, const T6 &o6,
292 const T7 &o7, const T8 &o8, const T9 &o9)
294 StringPrivate::Composition c(fmt);
295 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
299 template <typename T1, typename T2, typename T3, typename T4, typename T5,
300 typename T6, typename T7, typename T8, typename T9, typename T10>
301 inline std::string compose(const std::string &fmt,
302 const T1 &o1, const T2 &o2, const T3 &o3,
303 const T4 &o4, const T5 &o5, const T6 &o6,
304 const T7 &o7, const T8 &o8, const T9 &o9,
307 StringPrivate::Composition c(fmt);
308 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
313 template <typename T1, typename T2, typename T3, typename T4, typename T5,
314 typename T6, typename T7, typename T8, typename T9, typename T10,
316 inline std::string compose(const std::string &fmt,
317 const T1 &o1, const T2 &o2, const T3 &o3,
318 const T4 &o4, const T5 &o5, const T6 &o6,
319 const T7 &o7, const T8 &o8, const T9 &o9,
320 const T10 &o10, const T11 &o11)
322 StringPrivate::Composition c(fmt);
323 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
328 template <typename T1, typename T2, typename T3, typename T4, typename T5,
329 typename T6, typename T7, typename T8, typename T9, typename T10,
330 typename T11, typename T12>
331 inline std::string compose(const std::string &fmt,
332 const T1 &o1, const T2 &o2, const T3 &o3,
333 const T4 &o4, const T5 &o5, const T6 &o6,
334 const T7 &o7, const T8 &o8, const T9 &o9,
335 const T10 &o10, const T11 &o11, const T12 &o12)
337 StringPrivate::Composition c(fmt);
338 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
339 .arg(o10).arg(o11).arg(o12);
343 template <typename T1, typename T2, typename T3, typename T4, typename T5,
344 typename T6, typename T7, typename T8, typename T9, typename T10,
345 typename T11, typename T12, typename T13>
346 inline std::string compose(const std::string &fmt,
347 const T1 &o1, const T2 &o2, const T3 &o3,
348 const T4 &o4, const T5 &o5, const T6 &o6,
349 const T7 &o7, const T8 &o8, const T9 &o9,
350 const T10 &o10, const T11 &o11, const T12 &o12,
353 StringPrivate::Composition c(fmt);
354 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
355 .arg(o10).arg(o11).arg(o12).arg(o13);
359 template <typename T1, typename T2, typename T3, typename T4, typename T5,
360 typename T6, typename T7, typename T8, typename T9, typename T10,
361 typename T11, typename T12, typename T13, typename T14>
362 inline std::string compose(const std::string &fmt,
363 const T1 &o1, const T2 &o2, const T3 &o3,
364 const T4 &o4, const T5 &o5, const T6 &o6,
365 const T7 &o7, const T8 &o8, const T9 &o9,
366 const T10 &o10, const T11 &o11, const T12 &o12,
367 const T13 &o13, const T14 &o14)
369 StringPrivate::Composition c(fmt);
370 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
371 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
375 template <typename T1, typename T2, typename T3, typename T4, typename T5,
376 typename T6, typename T7, typename T8, typename T9, typename T10,
377 typename T11, typename T12, typename T13, typename T14,
379 inline std::string compose(const std::string &fmt,
380 const T1 &o1, const T2 &o2, const T3 &o3,
381 const T4 &o4, const T5 &o5, const T6 &o6,
382 const T7 &o7, const T8 &o8, const T9 &o9,
383 const T10 &o10, const T11 &o11, const T12 &o12,
384 const T13 &o13, const T14 &o14, const T15 &o15)
386 StringPrivate::Composition c(fmt);
387 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
388 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
395 #endif // STRING_COMPOSE_H