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 int16_t& obj)
127 #ifdef DCPOMATIC_WINDOWS
128 __mingw_snprintf(buffer, 64, "%" PRId16, obj);
130 snprintf(buffer, 64, "%" PRId16, obj);
136 inline void write(std::string& s, const uint16_t& obj)
139 #ifdef DCPOMATIC_WINDOWS
140 __mingw_snprintf(buffer, 64, "%" PRIu16, obj);
142 snprintf(buffer, 64, "%" PRIu16, obj);
148 inline void write(std::string& s, const int32_t& obj)
151 #ifdef DCPOMATIC_WINDOWS
152 __mingw_snprintf(buffer, 64, "%" PRId32, obj);
154 snprintf(buffer, 64, "%" PRId32, obj);
160 inline void write(std::string& s, const uint32_t& obj)
163 #ifdef DCPOMATIC_WINDOWS
164 __mingw_snprintf(buffer, 64, "%" PRIu32, obj);
166 snprintf(buffer, 64, "%" PRIu32, obj);
172 inline void write(std::string& s, const int64_t& obj)
175 #ifdef DCPOMATIC_WINDOWS
176 __mingw_snprintf(buffer, 64, "%" PRId64, obj);
178 snprintf(buffer, 64, "%" PRId64, obj);
184 inline void write(std::string& s, const uint64_t& obj)
187 #ifdef DCPOMATIC_WINDOWS
188 __mingw_snprintf(buffer, 64, "%" PRIu64, obj);
190 snprintf(buffer, 64, "%" PRIu64, obj);
196 inline void write(std::string& s, const float& obj)
199 snprintf(buffer, 64, "%f", obj);
204 inline void write(std::string& s, const char& obj)
210 inline void write(std::string& s, const double& obj)
213 snprintf(buffer, 64, "%f", obj);
218 inline void write(std::string& s, char const * const & obj)
224 inline void write(std::string& s, char* const & obj)
230 inline void write(std::string& s, const std::string& obj)
235 inline void write(std::string& s, wchar_t const * const & obj)
237 std::wstring ws (obj);
238 std::string w (ws.begin(), ws.end());
243 inline void write(std::string& s, const boost::filesystem::path & obj)
248 // implementation of class Composition
249 template <typename T>
250 inline Composition &Composition::arg(const T &obj)
254 if (!os.empty()) { // manipulators don't produce output
255 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
256 output_list::iterator pos = i->second;
259 output.insert(pos, os);
269 inline Composition::Composition(std::string fmt)
272 std::string::size_type b = 0, i = 0;
274 // fill in output with the strings between the %1 %2 %3 etc. and
275 // fill in specs with the positions
276 while (i < fmt.length()) {
277 if (fmt[i] == '%' && i + 1 < fmt.length()) {
278 if (fmt[i + 1] == '%') { // catch %%
279 fmt.replace(i, 2, "%");
282 else if (is_number(fmt[i + 1])) { // aha! a spec!
284 output.push_back(fmt.substr(b, i - b));
286 int n = 1; // number of digits
290 spec_no += char_to_int(fmt[i + n]);
293 } while (i + n < fmt.length() && is_number(fmt[i + n]));
296 output_list::iterator pos = output.end();
297 --pos; // safe since we have just inserted a string>
299 specs.insert(specification_map::value_type(spec_no, pos));
301 // jump over spec string
312 if (i - b > 0) // add the rest of the string
313 output.push_back(fmt.substr(b, i - b));
316 inline std::string Composition::str() const
321 for (output_list::const_iterator i = output.begin(), end = output.end();
329 // now for the real thing(s)
332 // a series of functions which accept a format string on the form "text %1
333 // more %2 less %3" and a number of templated parameters and spits out the
335 template <typename T1>
336 inline std::string compose(const std::string &fmt, const T1 &o1)
338 StringPrivate::Composition c(fmt);
343 template <typename T1, typename T2>
344 inline std::string compose(const std::string &fmt,
345 const T1 &o1, const T2 &o2)
347 StringPrivate::Composition c(fmt);
352 template <typename T1, typename T2, typename T3>
353 inline std::string compose(const std::string &fmt,
354 const T1 &o1, const T2 &o2, const T3 &o3)
356 StringPrivate::Composition c(fmt);
357 c.arg(o1).arg(o2).arg(o3);
361 template <typename T1, typename T2, typename T3, typename T4>
362 inline std::string compose(const std::string &fmt,
363 const T1 &o1, const T2 &o2, const T3 &o3,
366 StringPrivate::Composition c(fmt);
367 c.arg(o1).arg(o2).arg(o3).arg(o4);
371 template <typename T1, typename T2, typename T3, typename T4, typename T5>
372 inline std::string compose(const std::string &fmt,
373 const T1 &o1, const T2 &o2, const T3 &o3,
374 const T4 &o4, const T5 &o5)
376 StringPrivate::Composition c(fmt);
377 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
381 template <typename T1, typename T2, typename T3, typename T4, typename T5,
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)
387 StringPrivate::Composition c(fmt);
388 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
392 template <typename T1, typename T2, typename T3, typename T4, typename T5,
393 typename T6, typename T7>
394 inline std::string compose(const std::string &fmt,
395 const T1 &o1, const T2 &o2, const T3 &o3,
396 const T4 &o4, const T5 &o5, const T6 &o6,
399 StringPrivate::Composition c(fmt);
400 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
404 template <typename T1, typename T2, typename T3, typename T4, typename T5,
405 typename T6, typename T7, typename T8>
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)
411 StringPrivate::Composition c(fmt);
412 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
416 template <typename T1, typename T2, typename T3, typename T4, typename T5,
417 typename T6, typename T7, typename T8, typename T9>
418 inline std::string compose(const std::string &fmt,
419 const T1 &o1, const T2 &o2, const T3 &o3,
420 const T4 &o4, const T5 &o5, const T6 &o6,
421 const T7 &o7, const T8 &o8, const T9 &o9)
423 StringPrivate::Composition c(fmt);
424 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
428 template <typename T1, typename T2, typename T3, typename T4, typename T5,
429 typename T6, typename T7, typename T8, typename T9, typename T10>
430 inline std::string compose(const std::string &fmt,
431 const T1 &o1, const T2 &o2, const T3 &o3,
432 const T4 &o4, const T5 &o5, const T6 &o6,
433 const T7 &o7, const T8 &o8, const T9 &o9,
436 StringPrivate::Composition c(fmt);
437 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
442 template <typename T1, typename T2, typename T3, typename T4, typename T5,
443 typename T6, typename T7, typename T8, typename T9, typename T10,
445 inline std::string compose(const std::string &fmt,
446 const T1 &o1, const T2 &o2, const T3 &o3,
447 const T4 &o4, const T5 &o5, const T6 &o6,
448 const T7 &o7, const T8 &o8, const T9 &o9,
449 const T10 &o10, const T11 &o11)
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)
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>
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)
466 StringPrivate::Composition c(fmt);
467 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
468 .arg(o10).arg(o11).arg(o12);
472 template <typename T1, typename T2, typename T3, typename T4, typename T5,
473 typename T6, typename T7, typename T8, typename T9, typename T10,
474 typename T11, typename T12, typename T13>
475 inline std::string compose(const std::string &fmt,
476 const T1 &o1, const T2 &o2, const T3 &o3,
477 const T4 &o4, const T5 &o5, const T6 &o6,
478 const T7 &o7, const T8 &o8, const T9 &o9,
479 const T10 &o10, const T11 &o11, const T12 &o12,
482 StringPrivate::Composition c(fmt);
483 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
484 .arg(o10).arg(o11).arg(o12).arg(o13);
488 template <typename T1, typename T2, typename T3, typename T4, typename T5,
489 typename T6, typename T7, typename T8, typename T9, typename T10,
490 typename T11, typename T12, typename T13, typename T14>
491 inline std::string compose(const std::string &fmt,
492 const T1 &o1, const T2 &o2, const T3 &o3,
493 const T4 &o4, const T5 &o5, const T6 &o6,
494 const T7 &o7, const T8 &o8, const T9 &o9,
495 const T10 &o10, const T11 &o11, const T12 &o12,
496 const T13 &o13, const T14 &o14)
498 StringPrivate::Composition c(fmt);
499 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
500 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
504 template <typename T1, typename T2, typename T3, typename T4, typename T5,
505 typename T6, typename T7, typename T8, typename T9, typename T10,
506 typename T11, typename T12, typename T13, typename T14,
508 inline std::string compose(const std::string &fmt,
509 const T1 &o1, const T2 &o2, const T3 &o3,
510 const T4 &o4, const T5 &o5, const T6 &o6,
511 const T7 &o7, const T8 &o8, const T9 &o9,
512 const T10 &o10, const T11 &o11, const T12 &o12,
513 const T13 &o13, const T14 &o14, const T15 &o15)
515 StringPrivate::Composition c(fmt);
516 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
517 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
523 #endif // STRING_COMPOSE_H