/* Defines String::compose(fmt, arg...) for easy, i18n-friendly
* composition of strings.
*
* Version 1.0.
*
* Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>.
*
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
//
// Basic usage is like
//
// std::cout << String::compose("This is a %1x%2 matrix.", rows, cols);
//
// See http://www.cs.aau.dk/~olau/compose/ or the included README.compose for
// more details.
//
#ifndef STRING_COMPOSE_H
#define STRING_COMPOSE_H
#include <sstream>
#include <string>
#include <list>
#include <map> // for multimap
namespace StringPrivate
{
// the actual composition class - using string::compose is cleaner, so we
// hide it here
class Composition
{
public:
// initialize and prepare format string on the form "text %1 text %2 etc."
// supply an replacement argument starting from %1
template <typename T>
// compose and return string
private:
int arg_no;
// we store the output as a list - when the output string is requested, the
// list is concatenated to a string; this way we can keep iterators into
// the list instead of into a string where they're possibly invalidated on
// inserting a specification string
// the initial parse of the format string fills in the specification map
// with positions for each of the various %?s
};
// helper for converting spec string numbers
inline int char_to_int(char c)
{
switch (c) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
default: return -1000;
}
}
inline bool is_number(int n)
{
switch (n) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}
// implementation of class Composition
template <typename T>
{
++pos;
}
//os.clear();
++arg_no;
}
return *this;
}
: arg_no(1)
{
// fill in output with the strings between the %1 %2 %3 etc. and
// fill in specs with the positions
++i;
}
// save string
int n = 1; // number of digits
int spec_no = 0;
do {
spec_no *= 10;
++n;
spec_no /= 10;
--pos; // safe since we have just inserted a string>
// jump over spec string
i += n;
b = i;
}
else
++i;
}
else
++i;
}
if (i - b > 0) // add the rest of the string
}
{
// assemble string
i != end; ++i)
str += *i;
return str;
}
}
// now for the real thing(s)
namespace String
{
// a series of functions which accept a format string on the form "text %1
// more %2 less %3" and a number of templated parameters and spits out the
// composited string
template <typename T1>
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
typename T6>
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
typename T11>
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
{
return c.str();
}
typename T15>
{
return c.str();
}
}
#endif // STRING_COMPOSE_H