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 int32_t& obj)
127 #ifdef DCPOMATIC_WINDOWS
128 __mingw_snprintf(buffer, 64, "%" PRId32, obj);
130 snprintf(buffer, 64, "%" PRId32, obj);
136 inline void write(std::string& s, const uint32_t& obj)
139 #ifdef DCPOMATIC_WINDOWS
140 __mingw_snprintf(buffer, 64, "%" PRIu32, obj);
142 snprintf(buffer, 64, "%" PRIu32, obj);
148 inline void write(std::string& s, const int64_t& obj)
151 #ifdef DCPOMATIC_WINDOWS
152 __mingw_snprintf(buffer, 64, "%" PRId64, obj);
154 snprintf(buffer, 64, "%" PRId64, obj);
160 inline void write(std::string& s, const uint64_t& obj)
163 #ifdef DCPOMATIC_WINDOWS
164 __mingw_snprintf(buffer, 64, "%" PRIu64, obj);
166 snprintf(buffer, 64, "%" PRIu64, 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, wchar_t const & obj)
208 std::wstring ws (&obj);
209 std::string w (ws.begin(), ws.end());
214 inline void write(std::string& s, const std::string& obj)
220 inline void write(std::string& s, const boost::filesystem::path & obj)
225 // implementation of class Composition
226 template <typename T>
227 inline Composition &Composition::arg(const T &obj)
231 if (!os.empty()) { // manipulators don't produce output
232 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
233 output_list::iterator pos = i->second;
236 output.insert(pos, os);
246 inline Composition::Composition(std::string fmt)
249 std::string::size_type b = 0, i = 0;
251 // fill in output with the strings between the %1 %2 %3 etc. and
252 // fill in specs with the positions
253 while (i < fmt.length()) {
254 if (fmt[i] == '%' && i + 1 < fmt.length()) {
255 if (fmt[i + 1] == '%') { // catch %%
256 fmt.replace(i, 2, "%");
259 else if (is_number(fmt[i + 1])) { // aha! a spec!
261 output.push_back(fmt.substr(b, i - b));
263 int n = 1; // number of digits
267 spec_no += char_to_int(fmt[i + n]);
270 } while (i + n < fmt.length() && is_number(fmt[i + n]));
273 output_list::iterator pos = output.end();
274 --pos; // safe since we have just inserted a string>
276 specs.insert(specification_map::value_type(spec_no, pos));
278 // jump over spec string
289 if (i - b > 0) // add the rest of the string
290 output.push_back(fmt.substr(b, i - b));
293 inline std::string Composition::str() const
298 for (output_list::const_iterator i = output.begin(), end = output.end();
306 // now for the real thing(s)
309 // a series of functions which accept a format string on the form "text %1
310 // more %2 less %3" and a number of templated parameters and spits out the
312 template <typename T1>
313 inline std::string compose(const std::string &fmt, const T1 &o1)
315 StringPrivate::Composition c(fmt);
320 template <typename T1, typename T2>
321 inline std::string compose(const std::string &fmt,
322 const T1 &o1, const T2 &o2)
324 StringPrivate::Composition c(fmt);
329 template <typename T1, typename T2, typename T3>
330 inline std::string compose(const std::string &fmt,
331 const T1 &o1, const T2 &o2, const T3 &o3)
333 StringPrivate::Composition c(fmt);
334 c.arg(o1).arg(o2).arg(o3);
338 template <typename T1, typename T2, typename T3, typename T4>
339 inline std::string compose(const std::string &fmt,
340 const T1 &o1, const T2 &o2, const T3 &o3,
343 StringPrivate::Composition c(fmt);
344 c.arg(o1).arg(o2).arg(o3).arg(o4);
348 template <typename T1, typename T2, typename T3, typename T4, typename T5>
349 inline std::string compose(const std::string &fmt,
350 const T1 &o1, const T2 &o2, const T3 &o3,
351 const T4 &o4, const T5 &o5)
353 StringPrivate::Composition c(fmt);
354 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
358 template <typename T1, typename T2, typename T3, typename T4, typename T5,
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)
364 StringPrivate::Composition c(fmt);
365 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
369 template <typename T1, typename T2, typename T3, typename T4, typename T5,
370 typename T6, typename T7>
371 inline std::string compose(const std::string &fmt,
372 const T1 &o1, const T2 &o2, const T3 &o3,
373 const T4 &o4, const T5 &o5, const T6 &o6,
376 StringPrivate::Composition c(fmt);
377 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
381 template <typename T1, typename T2, typename T3, typename T4, typename T5,
382 typename T6, typename T7, typename T8>
383 inline std::string compose(const std::string &fmt,
384 const T1 &o1, const T2 &o2, const T3 &o3,
385 const T4 &o4, const T5 &o5, const T6 &o6,
386 const T7 &o7, const T8 &o8)
388 StringPrivate::Composition c(fmt);
389 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
393 template <typename T1, typename T2, typename T3, typename T4, typename T5,
394 typename T6, typename T7, typename T8, typename T9>
395 inline std::string compose(const std::string &fmt,
396 const T1 &o1, const T2 &o2, const T3 &o3,
397 const T4 &o4, const T5 &o5, const T6 &o6,
398 const T7 &o7, const T8 &o8, const T9 &o9)
400 StringPrivate::Composition c(fmt);
401 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
405 template <typename T1, typename T2, typename T3, typename T4, typename T5,
406 typename T6, typename T7, typename T8, typename T9, typename T10>
407 inline std::string compose(const std::string &fmt,
408 const T1 &o1, const T2 &o2, const T3 &o3,
409 const T4 &o4, const T5 &o5, const T6 &o6,
410 const T7 &o7, const T8 &o8, const T9 &o9,
413 StringPrivate::Composition c(fmt);
414 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
419 template <typename T1, typename T2, typename T3, typename T4, typename T5,
420 typename T6, typename T7, typename T8, typename T9, typename T10,
422 inline std::string compose(const std::string &fmt,
423 const T1 &o1, const T2 &o2, const T3 &o3,
424 const T4 &o4, const T5 &o5, const T6 &o6,
425 const T7 &o7, const T8 &o8, const T9 &o9,
426 const T10 &o10, const T11 &o11)
428 StringPrivate::Composition c(fmt);
429 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
434 template <typename T1, typename T2, typename T3, typename T4, typename T5,
435 typename T6, typename T7, typename T8, typename T9, typename T10,
436 typename T11, typename T12>
437 inline std::string compose(const std::string &fmt,
438 const T1 &o1, const T2 &o2, const T3 &o3,
439 const T4 &o4, const T5 &o5, const T6 &o6,
440 const T7 &o7, const T8 &o8, const T9 &o9,
441 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);
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>
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,
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);
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>
468 inline std::string compose(const std::string &fmt,
469 const T1 &o1, const T2 &o2, const T3 &o3,
470 const T4 &o4, const T5 &o5, const T6 &o6,
471 const T7 &o7, const T8 &o8, const T9 &o9,
472 const T10 &o10, const T11 &o11, const T12 &o12,
473 const T13 &o13, const T14 &o14)
475 StringPrivate::Composition c(fmt);
476 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
477 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
481 template <typename T1, typename T2, typename T3, typename T4, typename T5,
482 typename T6, typename T7, typename T8, typename T9, typename T10,
483 typename T11, typename T12, typename T13, typename T14,
485 inline std::string compose(const std::string &fmt,
486 const T1 &o1, const T2 &o2, const T3 &o3,
487 const T4 &o4, const T5 &o5, const T6 &o6,
488 const T7 &o7, const T8 &o8, const T9 &o9,
489 const T10 &o10, const T11 &o11, const T12 &o12,
490 const T13 &o13, const T14 &o14, const T15 &o15)
492 StringPrivate::Composition c(fmt);
493 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
494 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
500 #endif // STRING_COMPOSE_H