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 int& obj)
139 snprintf(buffer, 64, "%d", obj);
144 inline void write(std::string& s, const unsigned int& obj)
147 snprintf(buffer, 64, "%ud", obj);
152 inline void write(std::string& s, const long unsigned int& obj)
155 snprintf(buffer, 64, "%lu", obj);
160 inline void write(std::string& s, const float& obj)
163 snprintf(buffer, 64, "%f", obj);
168 inline void write(std::string& s, const char& obj)
174 inline void write(std::string& s, const double& obj)
177 snprintf(buffer, 64, "%f", obj);
182 inline void write(std::string& s, char const * const & obj)
188 inline void write(std::string& s, char* const & obj)
194 inline void write(std::string& s, const std::string& obj)
200 inline void write(std::string& s, const boost::filesystem::path & obj)
205 // implementation of class Composition
206 template <typename T>
207 inline Composition &Composition::arg(const T &obj)
211 if (!os.empty()) { // manipulators don't produce output
212 for (specification_map::const_iterator i = specs.lower_bound(arg_no), end = specs.upper_bound(arg_no); i != end; ++i) {
213 output_list::iterator pos = i->second;
216 output.insert(pos, os);
226 inline Composition::Composition(std::string fmt)
229 std::string::size_type b = 0, i = 0;
231 // fill in output with the strings between the %1 %2 %3 etc. and
232 // fill in specs with the positions
233 while (i < fmt.length()) {
234 if (fmt[i] == '%' && i + 1 < fmt.length()) {
235 if (fmt[i + 1] == '%') { // catch %%
236 fmt.replace(i, 2, "%");
239 else if (is_number(fmt[i + 1])) { // aha! a spec!
241 output.push_back(fmt.substr(b, i - b));
243 int n = 1; // number of digits
247 spec_no += char_to_int(fmt[i + n]);
250 } while (i + n < fmt.length() && is_number(fmt[i + n]));
253 output_list::iterator pos = output.end();
254 --pos; // safe since we have just inserted a string>
256 specs.insert(specification_map::value_type(spec_no, pos));
258 // jump over spec string
269 if (i - b > 0) // add the rest of the string
270 output.push_back(fmt.substr(b, i - b));
273 inline std::string Composition::str() const
278 for (output_list::const_iterator i = output.begin(), end = output.end();
286 // now for the real thing(s)
289 // a series of functions which accept a format string on the form "text %1
290 // more %2 less %3" and a number of templated parameters and spits out the
292 template <typename T1>
293 inline std::string compose(const std::string &fmt, const T1 &o1)
295 StringPrivate::Composition c(fmt);
300 template <typename T1, typename T2>
301 inline std::string compose(const std::string &fmt,
302 const T1 &o1, const T2 &o2)
304 StringPrivate::Composition c(fmt);
309 template <typename T1, typename T2, typename T3>
310 inline std::string compose(const std::string &fmt,
311 const T1 &o1, const T2 &o2, const T3 &o3)
313 StringPrivate::Composition c(fmt);
314 c.arg(o1).arg(o2).arg(o3);
318 template <typename T1, typename T2, typename T3, typename T4>
319 inline std::string compose(const std::string &fmt,
320 const T1 &o1, const T2 &o2, const T3 &o3,
323 StringPrivate::Composition c(fmt);
324 c.arg(o1).arg(o2).arg(o3).arg(o4);
328 template <typename T1, typename T2, typename T3, typename T4, typename T5>
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)
333 StringPrivate::Composition c(fmt);
334 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
338 template <typename T1, typename T2, typename T3, typename T4, typename T5,
340 inline std::string compose(const std::string &fmt,
341 const T1 &o1, const T2 &o2, const T3 &o3,
342 const T4 &o4, const T5 &o5, const T6 &o6)
344 StringPrivate::Composition c(fmt);
345 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
349 template <typename T1, typename T2, typename T3, typename T4, typename T5,
350 typename T6, typename T7>
351 inline std::string compose(const std::string &fmt,
352 const T1 &o1, const T2 &o2, const T3 &o3,
353 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).arg(o7);
361 template <typename T1, typename T2, typename T3, typename T4, typename T5,
362 typename T6, typename T7, typename T8>
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,
366 const T7 &o7, const T8 &o8)
368 StringPrivate::Composition c(fmt);
369 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
373 template <typename T1, typename T2, typename T3, typename T4, typename T5,
374 typename T6, typename T7, typename T8, typename T9>
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, const T9 &o9)
380 StringPrivate::Composition c(fmt);
381 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
385 template <typename T1, typename T2, typename T3, typename T4, typename T5,
386 typename T6, typename T7, typename T8, typename T9, typename T10>
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,
393 StringPrivate::Composition c(fmt);
394 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
399 template <typename T1, typename T2, typename T3, typename T4, typename T5,
400 typename T6, typename T7, typename T8, typename T9, typename T10,
402 inline std::string compose(const std::string &fmt,
403 const T1 &o1, const T2 &o2, const T3 &o3,
404 const T4 &o4, const T5 &o5, const T6 &o6,
405 const T7 &o7, const T8 &o8, const T9 &o9,
406 const T10 &o10, const T11 &o11)
408 StringPrivate::Composition c(fmt);
409 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
414 template <typename T1, typename T2, typename T3, typename T4, typename T5,
415 typename T6, typename T7, typename T8, typename T9, typename T10,
416 typename T11, typename T12>
417 inline std::string compose(const std::string &fmt,
418 const T1 &o1, const T2 &o2, const T3 &o3,
419 const T4 &o4, const T5 &o5, const T6 &o6,
420 const T7 &o7, const T8 &o8, const T9 &o9,
421 const T10 &o10, const T11 &o11, const T12 &o12)
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)
425 .arg(o10).arg(o11).arg(o12);
429 template <typename T1, typename T2, typename T3, typename T4, typename T5,
430 typename T6, typename T7, typename T8, typename T9, typename T10,
431 typename T11, typename T12, typename T13>
432 inline std::string compose(const std::string &fmt,
433 const T1 &o1, const T2 &o2, const T3 &o3,
434 const T4 &o4, const T5 &o5, const T6 &o6,
435 const T7 &o7, const T8 &o8, const T9 &o9,
436 const T10 &o10, const T11 &o11, const T12 &o12,
439 StringPrivate::Composition c(fmt);
440 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
441 .arg(o10).arg(o11).arg(o12).arg(o13);
445 template <typename T1, typename T2, typename T3, typename T4, typename T5,
446 typename T6, typename T7, typename T8, typename T9, typename T10,
447 typename T11, typename T12, typename T13, typename T14>
448 inline std::string compose(const std::string &fmt,
449 const T1 &o1, const T2 &o2, const T3 &o3,
450 const T4 &o4, const T5 &o5, const T6 &o6,
451 const T7 &o7, const T8 &o8, const T9 &o9,
452 const T10 &o10, const T11 &o11, const T12 &o12,
453 const T13 &o13, const T14 &o14)
455 StringPrivate::Composition c(fmt);
456 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
457 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
461 template <typename T1, typename T2, typename T3, typename T4, typename T5,
462 typename T6, typename T7, typename T8, typename T9, typename T10,
463 typename T11, typename T12, typename T13, typename T14,
465 inline std::string compose(const std::string &fmt,
466 const T1 &o1, const T2 &o2, const T3 &o3,
467 const T4 &o4, const T5 &o5, const T6 &o6,
468 const T7 &o7, const T8 &o8, const T9 &o9,
469 const T10 &o10, const T11 &o11, const T12 &o12,
470 const T13 &o13, const T14 &o14, const T15 &o15)
472 StringPrivate::Composition c(fmt);
473 c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
474 .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
480 #endif // STRING_COMPOSE_H