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
37 #include <dcp/locale_convert.h>
38 #include <boost/filesystem.hpp>
45 namespace StringPrivate
47 // the actual composition class - using string::compose is cleaner, so we
52 // initialize and prepare format string on the form "text %1 text %2 etc."
53 explicit Composition(std::string fmt);
55 // supply an replacement argument starting from %1
57 Composition &arg(const T &obj);
59 // compose and return string
60 std::string str() const;
66 // we store the output as a list - when the output string is requested, the
67 // list is concatenated to a string; this way we can keep iterators into
68 // the list instead of into a string where they're possibly invalidated on
69 // inserting a specification string
70 typedef std::list<std::string> output_list;
73 // the initial parse of the format string fills in the specification map
74 // with positions for each of the various %?s
75 typedef std::multimap<int, output_list::iterator> specification_map;
76 specification_map specs;
79 // helper for converting spec string numbers
80 inline int char_to_int(char c)
93 default: return -1000;
97 inline bool is_number(int n)
117 // implementation of class Composition
118 template <typename T>
119 inline Composition &Composition::arg(const T &obj)
121 os += dcp::locale_convert<std::string>(obj);
123 if (!os.empty()) { // manipulators don't produce output
124 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
125 output_list::iterator pos = i->second;
128 output.insert(pos, os);
138 inline Composition::Composition(std::string fmt)
141 std::string::size_type b = 0, i = 0;
143 // fill in output with the strings between the %1 %2 %3 etc. and
144 // fill in specs with the positions
145 while (i < fmt.length()) {
146 if (fmt[i] == '%' && i + 1 < fmt.length()) {
147 if (fmt[i + 1] == '%') { // catch %%
148 fmt.replace(i, 2, "%");
151 else if (is_number(fmt[i + 1])) { // aha! a spec!
153 output.push_back(fmt.substr(b, i - b));
155 int n = 1; // number of digits
159 spec_no += char_to_int(fmt[i + n]);
162 } while (i + n < fmt.length() && is_number(fmt[i + n]));
165 output_list::iterator pos = output.end();
166 --pos; // safe since we have just inserted a string>
168 specs.insert(specification_map::value_type(spec_no, pos));
170 // jump over spec string
181 if (i - b > 0) // add the rest of the string
182 output.push_back(fmt.substr(b, i - b));
185 inline std::string Composition::str() const
190 for (output_list::const_iterator i = output.begin(), end = output.end();
198 // now for the real thing(s)
201 // a series of functions which accept a format string on the form "text %1
202 // more %2 less %3" and a number of templated parameters and spits out the
204 template <typename T1>
205 inline std::string compose(const std::string &fmt, const T1 &o1)
207 StringPrivate::Composition c(fmt);
212 template <typename T1, typename T2>
213 inline std::string compose(const std::string &fmt,
214 const T1 &o1, const T2 &o2)
216 StringPrivate::Composition c(fmt);
221 template <typename T1, typename T2, typename T3>
222 inline std::string compose(const std::string &fmt,
223 const T1 &o1, const T2 &o2, const T3 &o3)
225 StringPrivate::Composition c(fmt);
226 c.arg(o1).arg(o2).arg(o3);
230 template <typename T1, typename T2, typename T3, typename T4>
231 inline std::string compose(const std::string &fmt,
232 const T1 &o1, const T2 &o2, const T3 &o3,
235 StringPrivate::Composition c(fmt);
236 c.arg(o1).arg(o2).arg(o3).arg(o4);
240 template <typename T1, typename T2, typename T3, typename T4, typename T5>
241 inline std::string compose(const std::string &fmt,
242 const T1 &o1, const T2 &o2, const T3 &o3,
243 const T4 &o4, const T5 &o5)
245 StringPrivate::Composition c(fmt);
246 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
250 template <typename T1, typename T2, typename T3, typename T4, typename T5,
252 inline std::string compose(const std::string &fmt,
253 const T1 &o1, const T2 &o2, const T3 &o3,
254 const T4 &o4, const T5 &o5, const T6 &o6)
256 StringPrivate::Composition c(fmt);
257 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
261 template <typename T1, typename T2, typename T3, typename T4, typename T5,
262 typename T6, typename T7>
263 inline std::string compose(const std::string &fmt,
264 const T1 &o1, const T2 &o2, const T3 &o3,
265 const T4 &o4, const T5 &o5, const T6 &o6,
268 StringPrivate::Composition c(fmt);
269 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
273 template <typename T1, typename T2, typename T3, typename T4, typename T5,
274 typename T6, typename T7, typename T8>
275 inline std::string compose(const std::string &fmt,
276 const T1 &o1, const T2 &o2, const T3 &o3,
277 const T4 &o4, const T5 &o5, const T6 &o6,
278 const T7 &o7, const T8 &o8)
280 StringPrivate::Composition c(fmt);
281 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
285 template <typename T1, typename T2, typename T3, typename T4, typename T5,
286 typename T6, typename T7, typename T8, typename T9>
287 inline std::string compose(const std::string &fmt,
288 const T1 &o1, const T2 &o2, const T3 &o3,
289 const T4 &o4, const T5 &o5, const T6 &o6,
290 const T7 &o7, const T8 &o8, const T9 &o9)
292 StringPrivate::Composition c(fmt);
293 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
297 template <typename T1, typename T2, typename T3, typename T4, typename T5,
298 typename T6, typename T7, typename T8, typename T9, typename T10>
299 inline std::string compose(const std::string &fmt,
300 const T1 &o1, const T2 &o2, const T3 &o3,
301 const T4 &o4, const T5 &o5, const T6 &o6,
302 const T7 &o7, const T8 &o8, const T9 &o9,
305 StringPrivate::Composition c(fmt);
306 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
311 template <typename T1, typename T2, typename T3, typename T4, typename T5,
312 typename T6, typename T7, typename T8, typename T9, typename T10,
314 inline std::string compose(const std::string &fmt,
315 const T1 &o1, const T2 &o2, const T3 &o3,
316 const T4 &o4, const T5 &o5, const T6 &o6,
317 const T7 &o7, const T8 &o8, const T9 &o9,
318 const T10 &o10, const T11 &o11)
320 StringPrivate::Composition c(fmt);
321 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
326 template <typename T1, typename T2, typename T3, typename T4, typename T5,
327 typename T6, typename T7, typename T8, typename T9, typename T10,
328 typename T11, typename T12>
329 inline std::string compose(const std::string &fmt,
330 const T1 &o1, const T2 &o2, const T3 &o3,
331 const T4 &o4, const T5 &o5, const T6 &o6,
332 const T7 &o7, const T8 &o8, const T9 &o9,
333 const T10 &o10, const T11 &o11, const T12 &o12)
335 StringPrivate::Composition c(fmt);
336 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
337 .arg(o10).arg(o11).arg(o12);
341 template <typename T1, typename T2, typename T3, typename T4, typename T5,
342 typename T6, typename T7, typename T8, typename T9, typename T10,
343 typename T11, typename T12, typename T13>
344 inline std::string compose(const std::string &fmt,
345 const T1 &o1, const T2 &o2, const T3 &o3,
346 const T4 &o4, const T5 &o5, const T6 &o6,
347 const T7 &o7, const T8 &o8, const T9 &o9,
348 const T10 &o10, const T11 &o11, const T12 &o12,
351 StringPrivate::Composition c(fmt);
352 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
353 .arg(o10).arg(o11).arg(o12).arg(o13);
357 template <typename T1, typename T2, typename T3, typename T4, typename T5,
358 typename T6, typename T7, typename T8, typename T9, typename T10,
359 typename T11, typename T12, typename T13, typename T14>
360 inline std::string compose(const std::string &fmt,
361 const T1 &o1, const T2 &o2, const T3 &o3,
362 const T4 &o4, const T5 &o5, const T6 &o6,
363 const T7 &o7, const T8 &o8, const T9 &o9,
364 const T10 &o10, const T11 &o11, const T12 &o12,
365 const T13 &o13, const T14 &o14)
367 StringPrivate::Composition c(fmt);
368 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
369 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
373 template <typename T1, typename T2, typename T3, typename T4, typename T5,
374 typename T6, typename T7, typename T8, typename T9, typename T10,
375 typename T11, typename T12, typename T13, typename T14,
377 inline std::string compose(const std::string &fmt,
378 const T1 &o1, const T2 &o2, const T3 &o3,
379 const T4 &o4, const T5 &o5, const T6 &o6,
380 const T7 &o7, const T8 &o8, const T9 &o9,
381 const T10 &o10, const T11 &o11, const T12 &o12,
382 const T13 &o13, const T14 &o14, const T15 &o15)
384 StringPrivate::Composition c(fmt);
385 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
386 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
392 #endif // STRING_COMPOSE_H