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 <boost/filesystem.hpp>
44 namespace StringPrivate
46 // the actual composition class - using string::compose is cleaner, so we
51 // initialize and prepare format string on the form "text %1 text %2 etc."
52 explicit Composition(std::string fmt);
54 // supply an replacement argument starting from %1
56 Composition &arg(const T &obj);
58 // compose and return string
59 std::string str() const;
65 // we store the output as a list - when the output string is requested, the
66 // list is concatenated to a string; this way we can keep iterators into
67 // the list instead of into a string where they're possibly invalidated on
68 // inserting a specification string
69 typedef std::list<std::string> output_list;
72 // the initial parse of the format string fills in the specification map
73 // with positions for each of the various %?s
74 typedef std::multimap<int, output_list::iterator> specification_map;
75 specification_map specs;
78 // helper for converting spec string numbers
79 inline int char_to_int(char c)
92 default: return -1000;
96 inline bool is_number(int n)
116 template <typename T>
117 inline void write(std::string& s, const T& obj)
119 /* Assume anything not specialized has a to_string() method */
120 s += to_string (obj);
124 inline void write(std::string& s, const int64_t& obj)
127 #ifdef DCPOMATIC_WINDOWS
128 __mingw_snprintf(buffer, 64, "%" PRId64, obj);
130 snprintf(buffer, 64, "%" PRId64, obj);
136 inline void write(std::string& s, const uint64_t& obj)
139 #ifdef DCPOMATIC_WINDOWS
140 __mingw_snprintf(buffer, 64, "%" PRIu64, obj);
142 snprintf(buffer, 64, "%" PRIu64, obj);
148 inline void write(std::string& s, const int& obj)
151 snprintf(buffer, 64, "%d", obj);
156 inline void write(std::string& s, const unsigned int& obj)
159 snprintf(buffer, 64, "%ud", obj);
164 inline void write(std::string& s, const float& obj)
167 snprintf(buffer, 64, "%f", obj);
172 inline void write(std::string& s, const char& obj)
178 inline void write(std::string& s, const double& obj)
181 snprintf(buffer, 64, "%f", obj);
186 inline void write(std::string& s, char const * const & obj)
192 inline void write(std::string& s, char* const & obj)
198 inline void write(std::string& s, const std::string& obj)
204 inline void write(std::string& s, const boost::filesystem::path & obj)
209 // implementation of class Composition
210 template <typename T>
211 inline Composition &Composition::arg(const T &obj)
215 if (!os.empty()) { // manipulators don't produce output
216 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
217 output_list::iterator pos = i->second;
220 output.insert(pos, os);
230 inline Composition::Composition(std::string fmt)
233 std::string::size_type b = 0, i = 0;
235 // fill in output with the strings between the %1 %2 %3 etc. and
236 // fill in specs with the positions
237 while (i < fmt.length()) {
238 if (fmt[i] == '%' && i + 1 < fmt.length()) {
239 if (fmt[i + 1] == '%') { // catch %%
240 fmt.replace(i, 2, "%");
243 else if (is_number(fmt[i + 1])) { // aha! a spec!
245 output.push_back(fmt.substr(b, i - b));
247 int n = 1; // number of digits
251 spec_no += char_to_int(fmt[i + n]);
254 } while (i + n < fmt.length() && is_number(fmt[i + n]));
257 output_list::iterator pos = output.end();
258 --pos; // safe since we have just inserted a string>
260 specs.insert(specification_map::value_type(spec_no, pos));
262 // jump over spec string
273 if (i - b > 0) // add the rest of the string
274 output.push_back(fmt.substr(b, i - b));
277 inline std::string Composition::str() const
282 for (output_list::const_iterator i = output.begin(), end = output.end();
290 // now for the real thing(s)
293 // a series of functions which accept a format string on the form "text %1
294 // more %2 less %3" and a number of templated parameters and spits out the
296 template <typename T1>
297 inline std::string compose(const std::string &fmt, const T1 &o1)
299 StringPrivate::Composition c(fmt);
304 template <typename T1, typename T2>
305 inline std::string compose(const std::string &fmt,
306 const T1 &o1, const T2 &o2)
308 StringPrivate::Composition c(fmt);
313 template <typename T1, typename T2, typename T3>
314 inline std::string compose(const std::string &fmt,
315 const T1 &o1, const T2 &o2, const T3 &o3)
317 StringPrivate::Composition c(fmt);
318 c.arg(o1).arg(o2).arg(o3);
322 template <typename T1, typename T2, typename T3, typename T4>
323 inline std::string compose(const std::string &fmt,
324 const T1 &o1, const T2 &o2, const T3 &o3,
327 StringPrivate::Composition c(fmt);
328 c.arg(o1).arg(o2).arg(o3).arg(o4);
332 template <typename T1, typename T2, typename T3, typename T4, typename T5>
333 inline std::string compose(const std::string &fmt,
334 const T1 &o1, const T2 &o2, const T3 &o3,
335 const T4 &o4, const T5 &o5)
337 StringPrivate::Composition c(fmt);
338 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
342 template <typename T1, typename T2, typename T3, typename T4, typename T5,
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)
348 StringPrivate::Composition c(fmt);
349 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
353 template <typename T1, typename T2, typename T3, typename T4, typename T5,
354 typename T6, typename T7>
355 inline std::string compose(const std::string &fmt,
356 const T1 &o1, const T2 &o2, const T3 &o3,
357 const T4 &o4, const T5 &o5, const T6 &o6,
360 StringPrivate::Composition c(fmt);
361 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
365 template <typename T1, typename T2, typename T3, typename T4, typename T5,
366 typename T6, typename T7, typename T8>
367 inline std::string compose(const std::string &fmt,
368 const T1 &o1, const T2 &o2, const T3 &o3,
369 const T4 &o4, const T5 &o5, const T6 &o6,
370 const T7 &o7, const T8 &o8)
372 StringPrivate::Composition c(fmt);
373 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
377 template <typename T1, typename T2, typename T3, typename T4, typename T5,
378 typename T6, typename T7, typename T8, typename T9>
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)
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);
389 template <typename T1, typename T2, typename T3, typename T4, typename T5,
390 typename T6, typename T7, typename T8, typename T9, typename T10>
391 inline std::string compose(const std::string &fmt,
392 const T1 &o1, const T2 &o2, const T3 &o3,
393 const T4 &o4, const T5 &o5, const T6 &o6,
394 const T7 &o7, const T8 &o8, const T9 &o9,
397 StringPrivate::Composition c(fmt);
398 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
403 template <typename T1, typename T2, typename T3, typename T4, typename T5,
404 typename T6, typename T7, typename T8, typename T9, typename T10,
406 inline std::string compose(const std::string &fmt,
407 const T1 &o1, const T2 &o2, const T3 &o3,
408 const T4 &o4, const T5 &o5, const T6 &o6,
409 const T7 &o7, const T8 &o8, const T9 &o9,
410 const T10 &o10, const T11 &o11)
412 StringPrivate::Composition c(fmt);
413 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
418 template <typename T1, typename T2, typename T3, typename T4, typename T5,
419 typename T6, typename T7, typename T8, typename T9, typename T10,
420 typename T11, typename T12>
421 inline std::string compose(const std::string &fmt,
422 const T1 &o1, const T2 &o2, const T3 &o3,
423 const T4 &o4, const T5 &o5, const T6 &o6,
424 const T7 &o7, const T8 &o8, const T9 &o9,
425 const T10 &o10, const T11 &o11, const T12 &o12)
427 StringPrivate::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);
433 template <typename T1, typename T2, typename T3, typename T4, typename T5,
434 typename T6, typename T7, typename T8, typename T9, typename T10,
435 typename T11, typename T12, typename T13>
436 inline std::string compose(const std::string &fmt,
437 const T1 &o1, const T2 &o2, const T3 &o3,
438 const T4 &o4, const T5 &o5, const T6 &o6,
439 const T7 &o7, const T8 &o8, const T9 &o9,
440 const T10 &o10, const T11 &o11, const T12 &o12,
443 StringPrivate::Composition c(fmt);
444 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
445 .arg(o10).arg(o11).arg(o12).arg(o13);
449 template <typename T1, typename T2, typename T3, typename T4, typename T5,
450 typename T6, typename T7, typename T8, typename T9, typename T10,
451 typename T11, typename T12, typename T13, typename T14>
452 inline std::string compose(const std::string &fmt,
453 const T1 &o1, const T2 &o2, const T3 &o3,
454 const T4 &o4, const T5 &o5, const T6 &o6,
455 const T7 &o7, const T8 &o8, const T9 &o9,
456 const T10 &o10, const T11 &o11, const T12 &o12,
457 const T13 &o13, const T14 &o14)
459 StringPrivate::Composition c(fmt);
460 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
461 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
465 template <typename T1, typename T2, typename T3, typename T4, typename T5,
466 typename T6, typename T7, typename T8, typename T9, typename T10,
467 typename T11, typename T12, typename T13, typename T14,
469 inline std::string compose(const std::string &fmt,
470 const T1 &o1, const T2 &o2, const T3 &o3,
471 const T4 &o4, const T5 &o5, const T6 &o6,
472 const T7 &o7, const T8 &o8, const T9 &o9,
473 const T10 &o10, const T11 &o11, const T12 &o12,
474 const T13 &o13, const T14 &o14, const T15 &o15)
476 StringPrivate::Composition c(fmt);
477 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
478 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
484 #endif // STRING_COMPOSE_H