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, "%" PRud64, 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 long unsigned int& obj)
167 snprintf(buffer, 64, "%lu", obj);
172 inline void write(std::string& s, const float& obj)
175 snprintf(buffer, 64, "%f", obj);
180 inline void write(std::string& s, const char& obj)
186 inline void write(std::string& s, const double& obj)
189 snprintf(buffer, 64, "%f", obj);
194 inline void write(std::string& s, char const * const & obj)
200 inline void write(std::string& s, char* const & obj)
206 inline void write(std::string& s, const std::string& obj)
212 inline void write(std::string& s, const boost::filesystem::path & obj)
217 // implementation of class Composition
218 template <typename T>
219 inline Composition &Composition::arg(const T &obj)
223 if (!os.empty()) { // manipulators don't produce output
224 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
225 output_list::iterator pos = i->second;
228 output.insert(pos, os);
238 inline Composition::Composition(std::string fmt)
241 std::string::size_type b = 0, i = 0;
243 // fill in output with the strings between the %1 %2 %3 etc. and
244 // fill in specs with the positions
245 while (i < fmt.length()) {
246 if (fmt[i] == '%' && i + 1 < fmt.length()) {
247 if (fmt[i + 1] == '%') { // catch %%
248 fmt.replace(i, 2, "%");
251 else if (is_number(fmt[i + 1])) { // aha! a spec!
253 output.push_back(fmt.substr(b, i - b));
255 int n = 1; // number of digits
259 spec_no += char_to_int(fmt[i + n]);
262 } while (i + n < fmt.length() && is_number(fmt[i + n]));
265 output_list::iterator pos = output.end();
266 --pos; // safe since we have just inserted a string>
268 specs.insert(specification_map::value_type(spec_no, pos));
270 // jump over spec string
281 if (i - b > 0) // add the rest of the string
282 output.push_back(fmt.substr(b, i - b));
285 inline std::string Composition::str() const
290 for (output_list::const_iterator i = output.begin(), end = output.end();
298 // now for the real thing(s)
301 // a series of functions which accept a format string on the form "text %1
302 // more %2 less %3" and a number of templated parameters and spits out the
304 template <typename T1>
305 inline std::string compose(const std::string &fmt, const T1 &o1)
307 StringPrivate::Composition c(fmt);
312 template <typename T1, typename T2>
313 inline std::string compose(const std::string &fmt,
314 const T1 &o1, const T2 &o2)
316 StringPrivate::Composition c(fmt);
321 template <typename T1, typename T2, typename T3>
322 inline std::string compose(const std::string &fmt,
323 const T1 &o1, const T2 &o2, const T3 &o3)
325 StringPrivate::Composition c(fmt);
326 c.arg(o1).arg(o2).arg(o3);
330 template <typename T1, typename T2, typename T3, typename T4>
331 inline std::string compose(const std::string &fmt,
332 const T1 &o1, const T2 &o2, const T3 &o3,
335 StringPrivate::Composition c(fmt);
336 c.arg(o1).arg(o2).arg(o3).arg(o4);
340 template <typename T1, typename T2, typename T3, typename T4, typename T5>
341 inline std::string compose(const std::string &fmt,
342 const T1 &o1, const T2 &o2, const T3 &o3,
343 const T4 &o4, const T5 &o5)
345 StringPrivate::Composition c(fmt);
346 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
350 template <typename T1, typename T2, typename T3, typename T4, typename T5,
352 inline std::string compose(const std::string &fmt,
353 const T1 &o1, const T2 &o2, const T3 &o3,
354 const T4 &o4, const T5 &o5, const T6 &o6)
356 StringPrivate::Composition c(fmt);
357 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
361 template <typename T1, typename T2, typename T3, typename T4, typename T5,
362 typename T6, typename T7>
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,
368 StringPrivate::Composition c(fmt);
369 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
373 template <typename T1, typename T2, typename T3, typename T4, typename T5,
374 typename T6, typename T7, typename T8>
375 inline std::string compose(const std::string &fmt,
376 const T1 &o1, const T2 &o2, const T3 &o3,
377 const T4 &o4, const T5 &o5, const T6 &o6,
378 const T7 &o7, const T8 &o8)
380 StringPrivate::Composition c(fmt);
381 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
385 template <typename T1, typename T2, typename T3, typename T4, typename T5,
386 typename T6, typename T7, typename T8, typename T9>
387 inline std::string compose(const std::string &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)
392 StringPrivate::Composition c(fmt);
393 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
397 template <typename T1, typename T2, typename T3, typename T4, typename T5,
398 typename T6, typename T7, typename T8, typename T9, typename T10>
399 inline std::string compose(const std::string &fmt,
400 const T1 &o1, const T2 &o2, const T3 &o3,
401 const T4 &o4, const T5 &o5, const T6 &o6,
402 const T7 &o7, const T8 &o8, const T9 &o9,
405 StringPrivate::Composition c(fmt);
406 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
411 template <typename T1, typename T2, typename T3, typename T4, typename T5,
412 typename T6, typename T7, typename T8, typename T9, typename T10,
414 inline std::string compose(const std::string &fmt,
415 const T1 &o1, const T2 &o2, const T3 &o3,
416 const T4 &o4, const T5 &o5, const T6 &o6,
417 const T7 &o7, const T8 &o8, const T9 &o9,
418 const T10 &o10, const T11 &o11)
420 StringPrivate::Composition c(fmt);
421 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
426 template <typename T1, typename T2, typename T3, typename T4, typename T5,
427 typename T6, typename T7, typename T8, typename T9, typename T10,
428 typename T11, typename T12>
429 inline std::string compose(const std::string &fmt,
430 const T1 &o1, const T2 &o2, const T3 &o3,
431 const T4 &o4, const T5 &o5, const T6 &o6,
432 const T7 &o7, const T8 &o8, const T9 &o9,
433 const T10 &o10, const T11 &o11, const T12 &o12)
435 StringPrivate::Composition c(fmt);
436 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
437 .arg(o10).arg(o11).arg(o12);
441 template <typename T1, typename T2, typename T3, typename T4, typename T5,
442 typename T6, typename T7, typename T8, typename T9, typename T10,
443 typename T11, typename T12, typename T13>
444 inline std::string compose(const std::string &fmt,
445 const T1 &o1, const T2 &o2, const T3 &o3,
446 const T4 &o4, const T5 &o5, const T6 &o6,
447 const T7 &o7, const T8 &o8, const T9 &o9,
448 const T10 &o10, const T11 &o11, const T12 &o12,
451 StringPrivate::Composition c(fmt);
452 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
453 .arg(o10).arg(o11).arg(o12).arg(o13);
457 template <typename T1, typename T2, typename T3, typename T4, typename T5,
458 typename T6, typename T7, typename T8, typename T9, typename T10,
459 typename T11, typename T12, typename T13, typename T14>
460 inline std::string compose(const std::string &fmt,
461 const T1 &o1, const T2 &o2, const T3 &o3,
462 const T4 &o4, const T5 &o5, const T6 &o6,
463 const T7 &o7, const T8 &o8, const T9 &o9,
464 const T10 &o10, const T11 &o11, const T12 &o12,
465 const T13 &o13, const T14 &o14)
467 StringPrivate::Composition c(fmt);
468 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
469 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
473 template <typename T1, typename T2, typename T3, typename T4, typename T5,
474 typename T6, typename T7, typename T8, typename T9, typename T10,
475 typename T11, typename T12, typename T13, typename T14,
477 inline std::string compose(const std::string &fmt,
478 const T1 &o1, const T2 &o2, const T3 &o3,
479 const T4 &o4, const T5 &o5, const T6 &o6,
480 const T7 &o7, const T8 &o8, const T9 &o9,
481 const T10 &o10, const T11 &o11, const T12 &o12,
482 const T13 &o13, const T14 &o14, const T15 &o15)
484 StringPrivate::Composition c(fmt);
485 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
486 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
492 #endif // STRING_COMPOSE_H