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 DCPOMATIC_STRING_COMPOSE_H
35 #define DCPOMATIC_STRING_COMPOSE_H
38 DCPOMATIC_DISABLE_WARNINGS
39 #include <dcp/locale_convert.h>
40 DCPOMATIC_ENABLE_WARNINGS
41 #include <boost/filesystem.hpp>
48 namespace StringPrivate
50 // the actual composition class - using string::compose is cleaner, so we
55 // initialize and prepare format string on the form "text %1 text %2 etc."
56 explicit Composition(std::string fmt);
58 // supply an replacement argument starting from %1
60 Composition &arg(const T &obj);
62 // compose and return string
63 std::string str() const;
69 // we store the output as a list - when the output string is requested, the
70 // list is concatenated to a string; this way we can keep iterators into
71 // the list instead of into a string where they're possibly invalidated on
72 // inserting a specification string
73 typedef std::list<std::string> output_list;
76 // the initial parse of the format string fills in the specification map
77 // with positions for each of the various %?s
78 typedef std::multimap<int, output_list::iterator> specification_map;
79 specification_map specs;
82 // helper for converting spec string numbers
83 inline int char_to_int(char c)
96 default: return -1000;
100 inline bool is_number(int n)
120 // implementation of class Composition
121 template <typename T>
122 inline Composition &Composition::arg(const T &obj)
124 os += dcp::locale_convert<std::string>(obj);
126 if (!os.empty()) { // manipulators don't produce output
127 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
128 output_list::iterator pos = i->second;
131 output.insert(pos, os);
141 inline Composition::Composition(std::string fmt)
144 std::string::size_type b = 0, i = 0;
146 // fill in output with the strings between the %1 %2 %3 etc. and
147 // fill in specs with the positions
148 while (i < fmt.length()) {
149 if (fmt[i] == '%' && i + 1 < fmt.length()) {
150 if (fmt[i + 1] == '%') { // catch %%
151 fmt.replace(i, 2, "%");
154 else if (is_number(fmt[i + 1])) { // aha! a spec!
156 output.push_back(fmt.substr(b, i - b));
158 int n = 1; // number of digits
162 spec_no += char_to_int(fmt[i + n]);
165 } while (i + n < fmt.length() && is_number(fmt[i + n]));
168 output_list::iterator pos = output.end();
169 --pos; // safe since we have just inserted a string>
171 specs.insert(specification_map::value_type(spec_no, pos));
173 // jump over spec string
184 if (i - b > 0) // add the rest of the string
185 output.push_back(fmt.substr(b, i - b));
188 inline std::string Composition::str() const
193 for (output_list::const_iterator i = output.begin(), end = output.end();
201 // now for the real thing(s)
204 // a series of functions which accept a format string on the form "text %1
205 // more %2 less %3" and a number of templated parameters and spits out the
207 template <typename T1>
208 inline std::string compose(const std::string &fmt, const T1 &o1)
210 StringPrivate::Composition c(fmt);
215 template <typename T1, typename T2>
216 inline std::string compose(const std::string &fmt,
217 const T1 &o1, const T2 &o2)
219 StringPrivate::Composition c(fmt);
224 template <typename T1, typename T2, typename T3>
225 inline std::string compose(const std::string &fmt,
226 const T1 &o1, const T2 &o2, const T3 &o3)
228 StringPrivate::Composition c(fmt);
229 c.arg(o1).arg(o2).arg(o3);
233 template <typename T1, typename T2, typename T3, typename T4>
234 inline std::string compose(const std::string &fmt,
235 const T1 &o1, const T2 &o2, const T3 &o3,
238 StringPrivate::Composition c(fmt);
239 c.arg(o1).arg(o2).arg(o3).arg(o4);
243 template <typename T1, typename T2, typename T3, typename T4, typename T5>
244 inline std::string compose(const std::string &fmt,
245 const T1 &o1, const T2 &o2, const T3 &o3,
246 const T4 &o4, const T5 &o5)
248 StringPrivate::Composition c(fmt);
249 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
253 template <typename T1, typename T2, typename T3, typename T4, typename T5,
255 inline std::string compose(const std::string &fmt,
256 const T1 &o1, const T2 &o2, const T3 &o3,
257 const T4 &o4, const T5 &o5, const T6 &o6)
259 StringPrivate::Composition c(fmt);
260 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
264 template <typename T1, typename T2, typename T3, typename T4, typename T5,
265 typename T6, typename T7>
266 inline std::string compose(const std::string &fmt,
267 const T1 &o1, const T2 &o2, const T3 &o3,
268 const T4 &o4, const T5 &o5, const T6 &o6,
271 StringPrivate::Composition c(fmt);
272 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
276 template <typename T1, typename T2, typename T3, typename T4, typename T5,
277 typename T6, typename T7, typename T8>
278 inline std::string compose(const std::string &fmt,
279 const T1 &o1, const T2 &o2, const T3 &o3,
280 const T4 &o4, const T5 &o5, const T6 &o6,
281 const T7 &o7, const T8 &o8)
283 StringPrivate::Composition c(fmt);
284 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
288 template <typename T1, typename T2, typename T3, typename T4, typename T5,
289 typename T6, typename T7, typename T8, typename T9>
290 inline std::string compose(const std::string &fmt,
291 const T1 &o1, const T2 &o2, const T3 &o3,
292 const T4 &o4, const T5 &o5, const T6 &o6,
293 const T7 &o7, const T8 &o8, const T9 &o9)
295 StringPrivate::Composition c(fmt);
296 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
300 template <typename T1, typename T2, typename T3, typename T4, typename T5,
301 typename T6, typename T7, typename T8, typename T9, typename T10>
302 inline std::string compose(const std::string &fmt,
303 const T1 &o1, const T2 &o2, const T3 &o3,
304 const T4 &o4, const T5 &o5, const T6 &o6,
305 const T7 &o7, const T8 &o8, const T9 &o9,
308 StringPrivate::Composition c(fmt);
309 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
314 template <typename T1, typename T2, typename T3, typename T4, typename T5,
315 typename T6, typename T7, typename T8, typename T9, typename T10,
317 inline std::string compose(const std::string &fmt,
318 const T1 &o1, const T2 &o2, const T3 &o3,
319 const T4 &o4, const T5 &o5, const T6 &o6,
320 const T7 &o7, const T8 &o8, const T9 &o9,
321 const T10 &o10, const T11 &o11)
323 StringPrivate::Composition c(fmt);
324 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
329 template <typename T1, typename T2, typename T3, typename T4, typename T5,
330 typename T6, typename T7, typename T8, typename T9, typename T10,
331 typename T11, typename T12>
332 inline std::string compose(const std::string &fmt,
333 const T1 &o1, const T2 &o2, const T3 &o3,
334 const T4 &o4, const T5 &o5, const T6 &o6,
335 const T7 &o7, const T8 &o8, const T9 &o9,
336 const T10 &o10, const T11 &o11, const T12 &o12)
338 StringPrivate::Composition c(fmt);
339 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
340 .arg(o10).arg(o11).arg(o12);
344 template <typename T1, typename T2, typename T3, typename T4, typename T5,
345 typename T6, typename T7, typename T8, typename T9, typename T10,
346 typename T11, typename T12, typename T13>
347 inline std::string compose(const std::string &fmt,
348 const T1 &o1, const T2 &o2, const T3 &o3,
349 const T4 &o4, const T5 &o5, const T6 &o6,
350 const T7 &o7, const T8 &o8, const T9 &o9,
351 const T10 &o10, const T11 &o11, const T12 &o12,
354 StringPrivate::Composition c(fmt);
355 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
356 .arg(o10).arg(o11).arg(o12).arg(o13);
360 template <typename T1, typename T2, typename T3, typename T4, typename T5,
361 typename T6, typename T7, typename T8, typename T9, typename T10,
362 typename T11, typename T12, typename T13, typename T14>
363 inline std::string compose(const std::string &fmt,
364 const T1 &o1, const T2 &o2, const T3 &o3,
365 const T4 &o4, const T5 &o5, const T6 &o6,
366 const T7 &o7, const T8 &o8, const T9 &o9,
367 const T10 &o10, const T11 &o11, const T12 &o12,
368 const T13 &o13, const T14 &o14)
370 StringPrivate::Composition c(fmt);
371 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
372 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
376 template <typename T1, typename T2, typename T3, typename T4, typename T5,
377 typename T6, typename T7, typename T8, typename T9, typename T10,
378 typename T11, typename T12, typename T13, typename T14,
380 inline std::string compose(const std::string &fmt,
381 const T1 &o1, const T2 &o2, const T3 &o3,
382 const T4 &o4, const T5 &o5, const T6 &o6,
383 const T7 &o7, const T8 &o8, const T9 &o9,
384 const T10 &o10, const T11 &o11, const T12 &o12,
385 const T13 &o13, const T14 &o14, const T15 &o15)
387 StringPrivate::Composition c(fmt);
388 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
389 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
395 #endif // STRING_COMPOSE_H