// tinyformat.h
// Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com]
//
// Boost Software License - Version 1.0
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//------------------------------------------------------------------------------
// Tinyformat: A minimal type safe printf-replacement library for C++
//
// This library aims to support 95% of casual C++ string formatting needs with
// a single lightweight header file.  Anything you can do with this library
// can also be done with the standard C++ streams, but probably with
// considerably more typing :)
//
// Design goals:
//
// * Simplicity and minimalism.  A single header file to include and distribute
//   with your own projects.
// * Type safety and extensibility for user defined types.
// * Parse standard C99 format strings, and support most features.
// * Support as many commonly used ``printf()`` features as practical without
//   compromising on simplicity.
//
//
// Example usage
// -------------
//
// To print the date, we might have
//
// std::string weekday = "Wednesday";
// const char* month = "July";
// long day = 27;
// int hour = 14;
// int min = 44;
//
// tfm::format(std::cout, "%s, %s %d, %.2d:%.2d\n",
//             weekday, month, day, hour, min);
//
// (The types here are intentionally odd to emphasize the type safety of the
// interface.)  The same thing could be achieved using either of the two
// convenience functions.  One returns a std::string:
//
// std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n",
//                                weekday, month, day, hour, min);
// std::cout << date;
//
// The other prints to the std::cout stream:
//
// tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
//
//
// Brief outline of functionality
// ------------------------------
//
// (For full docs, see the accompanying README)
//
//
// Interface functions:
//
//  template<typename T1, typename T2, ...>
//  void format(std::ostream& stream, const char* formatString,
//              const T1& value1, const T2& value1, ...)
//
//  template<typename T1, typename T2, ...>
//  std::string format(const char* formatString,
//                     const T1& value1, const T2& value1, ...)
//
//  template<typename T1, typename T2, ...>
//  void printf(const char* formatString,
//              const T1& value1, const T2& value1, ...)
//
//
// Error handling: Define TINYFORMAT_ERROR to customize the error handling for
// format strings which are unsupported or have the wrong number of format
// specifiers (calls assert() by default).
//
// User defined types: Uses operator<< for user defined types by default.
// Overload formatValue() for more control.
//
// Wrapping tfm::format inside a user defined format function: See the macros
// TINYFORMAT_WRAP_FORMAT and TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS.



#ifndef TINYFORMAT_H_INCLUDED
#define TINYFORMAT_H_INCLUDED

namespace tinyformat {}
//------------------------------------------------------------------------------
// Config section.  Customize to your liking!

// Namespace alias to encourage brevity
namespace tfm = tinyformat;

// Error handling; calls assert() by default.
// #define TINYFORMAT_ERROR(reasonString) your_error_handler(reasonString)

// Define for C++0x variadic templates which make the code shorter & more
// general.  If you don't define this, C++0x support is autodetected below.
// #define TINYFORMAT_USE_VARIADIC_TEMPLATES


//------------------------------------------------------------------------------
// Implementation details.
#include <cassert>
#include <iostream>
#include <sstream>

#ifndef TINYFORMAT_ERROR
#   define TINYFORMAT_ERROR(reason) assert(0 && reason)
#endif

#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
#   ifdef __GXX_EXPERIMENTAL_CXX0X__
#       define TINYFORMAT_USE_VARIADIC_TEMPLATES
#   endif
#endif

#ifdef __GNUC__
#   define TINYFORMAT_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#   define TINYFORMAT_NOINLINE __declspec(noinline)
#else
#   define TINYFORMAT_NOINLINE
#endif


namespace tinyformat {

//------------------------------------------------------------------------------
namespace detail {

// Test whether type T1 is convertible to type T2
template <typename T1, typename T2>
struct is_convertible
{
    private:
        // two types of different size
        struct fail { char dummy[2]; };
        struct succeed { char dummy; };
        // Try to convert a T1 to a T2 by plugging into tryConvert
        static fail tryConvert(...);
        static succeed tryConvert(const T2&);
        static const T1& makeT1();
    public:
#       ifdef _MSC_VER
        // Disable spurious loss of precision warning in tryConvert(makeT1())
#       pragma warning(push)
#       pragma warning(disable:4244)
#       endif
        // Standard trick: the (...) version of tryConvert will be chosen from
        // the overload set only if the version taking a T2 doesn't match.
        // Then we compare the sizes of the return types to check which
        // function matched.  Very neat, in a disgusting kind of way :)
        static const bool value =
            sizeof(tryConvert(makeT1())) == sizeof(succeed);
#       ifdef _MSC_VER
#       pragma warning(pop)
#       endif
};


// Format the value by casting to type fmtT.  This default implementation
// should never be called.
template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
struct formatValueAsType
{
    static void invoke(std::ostream& out, const T& value) { assert(0); }
};
// Specialized version for types that can actually be converted to fmtT, as
// indicated by the "convertible" template parameter.
template<typename T, typename fmtT>
struct formatValueAsType<T,fmtT,true>
{
    static void invoke(std::ostream& out, const T& value)
        { out << static_cast<fmtT>(value); }
};


// Convert an arbitrary type to integer.  The version with convertible=false
// throws an error.
template<typename T, bool convertible = is_convertible<T,int>::value>
struct convertToInt
{
    static int invoke(const T& value)
    {
        TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to "
                         "integer for use as variable width or precision");
        return 0;
    }
};
// Specialization for convertToInt when conversion is possible
template<typename T>
struct convertToInt<T,true>
{
    static int invoke(const T& value) { return static_cast<int>(value); }
};

} // namespace detail


//------------------------------------------------------------------------------
// Variable formatting functions.  May be overridden for user-defined types if
// desired.


// Format a value into a stream. Called from format() for all types by default.
//
// Users may override this for their own types.  When this function is called,
// the stream flags will have been modified according to the format string.
// The format specification is provided in the range [fmtBegin, fmtEnd).
//
// By default, formatValue() uses the usual stream insertion operator
// operator<< to format the type T, with special cases for the %c and %p
// conversions.
template<typename T>
inline void formatValue(std::ostream& out, const char* fmtBegin,
                        const char* fmtEnd, const T& value)
{
    // The mess here is to support the %c and %p conversions: if these
    // conversions are active we try to convert the type to a char or const
    // void* respectively and format that instead of the value itself.  For the
    // %p conversion it's important to avoid dereferencing the pointer, which
    // could otherwise lead to a crash when printing a dangling (const char*).
    const bool canConvertToChar = detail::is_convertible<T,char>::value;
    const bool canConvertToVoidPtr = detail::is_convertible<T, const void*>::value;
    if(canConvertToChar && *(fmtEnd-1) == 'c')
        detail::formatValueAsType<T, char>::invoke(out, value);
    else if(canConvertToVoidPtr && *(fmtEnd-1) == 'p')
        detail::formatValueAsType<T, const void*>::invoke(out, value);
    else
        out << value;
}


// Overloaded version for char types to support printing as an integer
#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType)                  \
inline void formatValue(std::ostream& out, const char* fmtBegin,      \
                        const char* fmtEnd, charType value)           \
{                                                                     \
    switch(*(fmtEnd-1))                                               \
    {                                                                 \
        case 'u': case 'd': case 'i': case 'o': case 'X': case 'x':   \
            out << static_cast<int>(value); break;                    \
        default:                                                      \
            out << value;                   break;                    \
    }                                                                 \
}
// per 3.9.1: char, signed char and unsigned char are all distinct types
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(char)
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(signed char)
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(unsigned char)
#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR


namespace detail {

// Class holding current position in format string and an output stream into
// which arguments are formatted.
class FormatIterator
{
    public:
        // Flags for features not representable with standard stream state
        enum ExtraFormatFlags
        {
            Flag_TruncateToPrecision = 1<<0, // truncate length to stream precision()
            Flag_SpacePadPositive    = 1<<1, // pad positive values with spaces
            Flag_VariableWidth       = 1<<2, // variable field width in arg list
            Flag_VariablePrecision   = 1<<3, // variable field precision in arg list
        };

        // out is the output stream, fmt is the full format string
        FormatIterator(std::ostream& out, const char* fmt)
            : m_out(out),
            m_fmt(fmt),
            m_extraFlags(0),
            m_wantWidth(false),
            m_wantPrecision(false),
            m_variableWidth(0),
            m_variablePrecision(0),
            m_origWidth(out.width()),
            m_origPrecision(out.precision()),
            m_origFlags(out.flags()),
            m_origFill(out.fill())
        { }

        // Print remaining part of format string.
        void finish()
        {
            // It would be nice if we could do this from the destructor, but we
            // can't if TINFORMAT_ERROR is used to throw an exception!
            m_fmt = printFormatStringLiteral(m_out, m_fmt);
            if(*m_fmt != '\0')
                TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
        }

        ~FormatIterator()
        {
            // Restore stream state
            m_out.width(m_origWidth);
            m_out.precision(m_origPrecision);
            m_out.flags(m_origFlags);
            m_out.fill(m_origFill);
        }

        template<typename T>
        void accept(const T& value);

    private:
        // Parse and return an integer from the string c, as atoi()
        // On return, c is set to one past the end of the integer.
        static int parseIntAndAdvance(const char*& c)
        {
            int i = 0;
            for(;*c >= '0' && *c <= '9'; ++c)
                i = 10*i + (*c - '0');
            return i;
        }

        // Format at most truncLen characters of a C string to the given
        // stream.  Return true if formatting proceeded (generic version always
        // returns false)
        template<typename T>
        static bool formatCStringTruncate(std::ostream& out, const T& value,
                                        std::streamsize truncLen)
        {
            return false;
        }
#       define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type)            \
        static bool formatCStringTruncate(std::ostream& out, type* value,  \
                                        std::streamsize truncLen)          \
        {                                                                  \
            std::streamsize len = 0;                                       \
            while(len < truncLen && value[len] != 0)                       \
                ++len;                                                     \
            out.write(value, len);                                         \
            return true;                                                   \
        }
        // Overload for const char* and char*.  Could overload for signed &
        // unsigned char too, but these are technically unneeded for printf
        // compatibility.
        TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(const char)
        TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(char)
#       undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE

        // Print literal part of format string and return next format spec
        // position.
        //
        // Skips over any occurrences of '%%', printing a literal '%' to the
        // output.  The position of the first % character of the next
        // nontrivial format spec is returned, or the end of string.
        static const char* printFormatStringLiteral(std::ostream& out,
                                                    const char* fmt)
        {
            const char* c = fmt;
            for(; true; ++c)
            {
                switch(*c)
                {
                    case '\0':
                        out.write(fmt, static_cast<std::streamsize>(c - fmt));
                        return c;
                    case '%':
                        out.write(fmt, static_cast<std::streamsize>(c - fmt));
                        if(*(c+1) != '%')
                            return c;
                        // for "%%", tack trailing % onto next literal section.
                        fmt = ++c;
                        break;
                }
            }
        }

        static const char* streamStateFromFormat(std::ostream& out,
                                                 unsigned int& extraFlags,
                                                 const char* fmtStart,
                                                 int variableWidth,
                                                 int variablePrecision);

        // Stream, current format string & state
        std::ostream& m_out;
        const char* m_fmt;
        unsigned int m_extraFlags;
        // State machine info for handling of variable width & precision
        bool m_wantWidth;
        bool m_wantPrecision;
        int m_variableWidth;
        int m_variablePrecision;
        // Saved stream state
        std::streamsize m_origWidth;
        std::streamsize m_origPrecision;
        std::ios::fmtflags m_origFlags;
        char m_origFill;
};


// Accept a value for formatting into the internal stream.
template<typename T>
TINYFORMAT_NOINLINE  //< greatly reduces bloat in optimized builds
void FormatIterator::accept(const T& value)
{
    // Parse the format string
    const char* fmtEnd = 0;
    if(m_extraFlags == 0 && !m_wantWidth && !m_wantPrecision)
    {
        m_fmt = printFormatStringLiteral(m_out, m_fmt);
        fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0);
        m_wantWidth     = (m_extraFlags & Flag_VariableWidth) != 0;
        m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0;
    }
    // Consume value as variable width and precision specifier if necessary
    if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision))
    {
        if(m_wantWidth || m_wantPrecision)
        {
            int v = convertToInt<T>::invoke(value);
            if(m_wantWidth)
            {
                m_variableWidth = v;
                m_wantWidth = false;
            }
            else if(m_wantPrecision)
            {
                m_variablePrecision = v;
                m_wantPrecision = false;
            }
            return;
        }
        // If we get here, we've set both the variable precision and width as
        // required and we need to rerun the stream state setup to insert these.
        fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt,
                                       m_variableWidth, m_variablePrecision);
    }

    // Format the value into the stream.
    if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision)))
        formatValue(m_out, m_fmt, fmtEnd, value);
    else
    {
        // The following are special cases where there's no direct
        // correspondence between stream formatting and the printf() behaviour.
        // Instead, we simulate the behaviour crudely by formatting into a
        // temporary string stream and munging the resulting string.
        std::ostringstream tmpStream;
        tmpStream.copyfmt(m_out);
        if(m_extraFlags & Flag_SpacePadPositive)
            tmpStream.setf(std::ios::showpos);
        // formatCStringTruncate is required for truncating conversions like
        // "%.4s" where at most 4 characters of the c-string should be read.
        // If we didn't include this special case, we might read off the end.
        if(!( (m_extraFlags & Flag_TruncateToPrecision) &&
             formatCStringTruncate(tmpStream, value, m_out.precision()) ))
        {
            // Not a truncated c-string; just format normally.
            formatValue(tmpStream, m_fmt, fmtEnd, value);
        }
        std::string result = tmpStream.str(); // allocates... yuck.
        if(m_extraFlags & Flag_SpacePadPositive)
        {
            for(size_t i = 0, iend = result.size(); i < iend; ++i)
                if(result[i] == '+')
                    result[i] = ' ';
        }
        if((m_extraFlags & Flag_TruncateToPrecision) &&
           (int)result.size() > (int)m_out.precision())
            m_out.write(result.c_str(), m_out.precision());
        else
            m_out << result;
    }
    m_extraFlags = 0;
    m_fmt = fmtEnd;
}


// Parse a format string and set the stream state accordingly.
//
// The format mini-language recognized here is meant to be the one from C99,
// with the form "%[flags][width][.precision][length]type".
//
// Formatting options which can't be natively represented using the ostream
// state are returned in the extraFlags parameter which is a bitwise
// combination of values from the ExtraFormatFlags enum.
inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
                                                         unsigned int& extraFlags,
                                                         const char* fmtStart,
                                                         int variableWidth,
                                                         int variablePrecision)
{
    if(*fmtStart != '%')
    {
        TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
        return fmtStart;
    }
    // Reset stream state to defaults.
    out.width(0);
    out.precision(6);
    out.fill(' ');
    // Reset most flags; ignore irrelevant unitbuf & skipws.
    out.unsetf(std::ios::adjustfield | std::ios::basefield |
               std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
               std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
    extraFlags = 0;
    bool precisionSet = false;
    bool widthSet = false;
    const char* c = fmtStart + 1;
    // 1) Parse flags
    for(;; ++c)
    {
        switch(*c)
        {
            case '#':
                out.setf(std::ios::showpoint | std::ios::showbase);
                continue;
            case '0':
                // overridden by left alignment ('-' flag)
                if(!(out.flags() & std::ios::left))
                {
                    // Use internal padding so that numeric values are
                    // formatted correctly, eg -00010 rather than 000-10
                    out.fill('0');
                    out.setf(std::ios::internal, std::ios::adjustfield);
                }
                continue;
            case '-':
                out.fill(' ');
                out.setf(std::ios::left, std::ios::adjustfield);
                continue;
            case ' ':
                // overridden by show positive sign, '+' flag.
                if(!(out.flags() & std::ios::showpos))
                    extraFlags |= Flag_SpacePadPositive;
                continue;
            case '+':
                out.setf(std::ios::showpos);
                extraFlags &= ~Flag_SpacePadPositive;
                continue;
        }
        break;
    }
    // 2) Parse width
    if(*c >= '0' && *c <= '9')
    {
        widthSet = true;
        out.width(parseIntAndAdvance(c));
    }
    if(*c == '*')
    {
        widthSet = true;
        if(variableWidth < 0)
        {
            // negative widths correspond to '-' flag set
            out.fill(' ');
            out.setf(std::ios::left, std::ios::adjustfield);
            variableWidth = -variableWidth;
        }
        out.width(variableWidth);
        extraFlags |= Flag_VariableWidth;
        ++c;
    }
    // 3) Parse precision
    if(*c == '.')
    {
        ++c;
        int precision = 0;
        if(*c == '*')
        {
            ++c;
            extraFlags |= Flag_VariablePrecision;
            precision = variablePrecision;
        }
        else
        {
            if(*c >= '0' && *c <= '9')
                precision = parseIntAndAdvance(c);
            else if(*c == '-') // negative precisions ignored, treated as zero.
                parseIntAndAdvance(++c);
        }
        out.precision(precision);
        precisionSet = true;
    }
    // 4) Ignore any C99 length modifier
    while(*c == 'l' || *c == 'h' || *c == 'L' ||
          *c == 'j' || *c == 'z' || *c == 't')
        ++c;
    // 5) We're up to the conversion specifier character.
    // Set stream flags based on conversion specifier (thanks to the
    // boost::format class for forging the way here).
    bool intConversion = false;
    switch(*c)
    {
        case 'u': case 'd': case 'i':
            out.setf(std::ios::dec, std::ios::basefield);
            intConversion = true;
            break;
        case 'o':
            out.setf(std::ios::oct, std::ios::basefield);
            intConversion = true;
            break;
        case 'X':
            out.setf(std::ios::uppercase);
        case 'x': case 'p':
            out.setf(std::ios::hex, std::ios::basefield);
            intConversion = true;
            break;
        case 'E':
            out.setf(std::ios::uppercase);
        case 'e':
            out.setf(std::ios::scientific, std::ios::floatfield);
            out.setf(std::ios::dec, std::ios::basefield);
            break;
        case 'F':
            out.setf(std::ios::uppercase);
        case 'f':
            out.setf(std::ios::fixed, std::ios::floatfield);
            break;
        case 'G':
            out.setf(std::ios::uppercase);
        case 'g':
            out.setf(std::ios::dec, std::ios::basefield);
            // As in boost::format, let stream decide float format.
            out.flags(out.flags() & ~std::ios::floatfield);
            break;
        case 'a': case 'A':
            break; // C99 hexadecimal floating point??  punt!
        case 'c':
            // Handled as special case inside formatValue()
            break;
        case 's':
            if(precisionSet)
                extraFlags |= Flag_TruncateToPrecision;
            // Make %s print booleans as "true" and "false"
            out.setf(std::ios::boolalpha);
            break;
        case 'n':
            // Not supported - will cause problems!
            TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported");
            break;
        case '\0':
            TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
                             "terminated by end of string");
            return c;
    }
    if(intConversion && precisionSet && !widthSet)
    {
        // "precision" for integers gives the minimum number of digits (to be
        // padded with zeros on the left).  This isn't really supported by the
        // iostreams, but we can approximately simulate it with the width if
        // the width isn't otherwise used.
        out.width(out.precision());
        out.setf(std::ios::internal, std::ios::adjustfield);
        out.fill('0');
    }
    return c+1;
}



//------------------------------------------------------------------------------
// Private format function on top of which the public interface is implemented
inline void format(FormatIterator& fmtIter)
{
    fmtIter.finish();
}

// Define N-argument format function.
//
// There's two cases here: c++0x and c++98.
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES

// First, the simple definition for C++0x:
template<typename T1, typename... Args>
void format(FormatIterator& fmtIter, const T1& value1, const Args&... args)
{
    fmtIter.accept(value1);
    format(fmtIter, args...);
}

#else

// For C++98 we don't have variadic templates so we need to generate code
// outside the language.  We could do this with some ugly macros but instead
// let's use a short snippet of python code with the help of the excellent cog
// code generation script ( http://nedbatchelder.com/code/cog/ )

/*[[[cog

maxParams = 12

# prepend a comma if the string isn't empty.
def prependComma(str):
    return '' if str == '' else ', ' + str

# Append backslashes to lines so they appear as a macro in C++
# lineLen is the desired padding before the backslash
def formatAsMacro(str, lineLen=75):
    lines = str.splitlines()
    lines = [l+' '*max(1, lineLen-len(l)) for l in lines]
    return '\\\n'.join(lines) + '\\'

# Fill out the given string template.
def fillTemplate(template, minParams=0, formatFunc=lambda s: s):
    for i in range(minParams,maxParams+1):
        paramRange = range(1,i+1)
        templateSpec = ', '.join(['typename T%d' % (j,) for j in paramRange])
        if templateSpec == '':
            templateSpec = 'inline'
        else:
            templateSpec = 'template<%s>' % (templateSpec,)
        paramList = prependComma(', '.join(['const T%d& v%d' % (j,j)
                                            for j in paramRange]))
        argList = prependComma(', '.join(['v%d' % (j,) for j in paramRange]))
        argListNoHead = prependComma(', '.join(['v%d' % (j,)
                                                for j in paramRange[1:]]))
        cog.outl(formatFunc(template % locals()))

fillTemplate(
'''%(templateSpec)s
void format(FormatIterator& fmtIter %(paramList)s)
{
    fmtIter.accept(v1);
    format(fmtIter%(argListNoHead)s);
}''', minParams=1)

]]]*/
template<typename T1>
void format(FormatIterator& fmtIter , const T1& v1)
{
    fmtIter.accept(v1);
    format(fmtIter);
}
template<typename T1, typename T2>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2)
{
    fmtIter.accept(v1);
    format(fmtIter, v2);
}
template<typename T1, typename T2, typename T3>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3);
}
template<typename T1, typename T2, typename T3, typename T4>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7, v8);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
void format(FormatIterator& fmtIter , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12)
{
    fmtIter.accept(v1);
    format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
}
//[[[end]]]

#endif // End C++98 variadic template emulation for format()

} // namespace detail


//------------------------------------------------------------------------------
// Define the macro TINYFORMAT_WRAP_FORMAT, which can be used to wrap a call
// to tfm::format for C++98 support.
//
// We make this available in both C++0x and C++98 mode for convenience so that
// users can choose not to write out the C++0x version if they're primarily
// interested in C++98 support, but still have things work with C++0x.
//
// Note that TINYFORMAT_WRAP_EXTRA_ARGS cannot be a macro parameter because it
// must expand to a comma separated list (or nothing, as used for printf below)

/*[[[cog
cog.outl(formatAsMacro(
'''#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix,
                               bodyPrefix, streamName, bodySuffix)'''))

fillTemplate(
r'''%(templateSpec)s
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt
                    %(paramList)s) funcDeclSuffix
{
    bodyPrefix
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);
    tinyformat::detail::format(fmtIter%(argList)s);
    bodySuffix
}''', minParams=0, formatFunc=formatAsMacro)
cog.outl()

]]]*/
#ifndef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
#endif


#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix,       \
                               bodyPrefix, streamName, bodySuffix)         \
inline                                                                     \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    ) funcDeclSuffix                                       \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter);                                   \
    bodySuffix                                                             \
}                                                                          \
template<typename T1>                                                      \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1) funcDeclSuffix                         \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1);                               \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2>                                         \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2) funcDeclSuffix           \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2);                           \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3>                            \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3);                       \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4>               \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4);                   \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5>  \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5);               \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6);           \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7);       \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8);   \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9); \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); \
    bodySuffix                                                             \
}                                                                          \
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12> \
returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt      \
                    , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12) funcDeclSuffix \
{                                                                          \
    bodyPrefix                                                             \
    tinyformat::detail::FormatIterator fmtIter(streamName, fmt);           \
    tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); \
    bodySuffix                                                             \
}                                                                          \

//[[[end]]]


//------------------------------------------------------------------------------
// Implement all the main interface functions here in terms of detail::format()

// Again, there's two cases.
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES

// C++0x - the simple case
template<typename... Args>
void format(std::ostream& out, const char* fmt, const Args&... args)
{
    detail::FormatIterator fmtIter(out, fmt);
    format(fmtIter, args...);
}

template<typename... Args>
std::string format(const char* fmt, const Args&... args)
{
    std::ostringstream oss;
    format(oss, fmt, args...);
    return oss.str();
}

template<typename... Args>
void printf(const char* fmt, const Args&... args)
{
    format(std::cout, fmt, args...);
}

#else

// C++98 - define the convenience functions using the wrapping macros

// template<typename... Args>
// void format(std::ostream& out, const char* fmt, const Args&... args)
#undef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS std::ostream& out,
TINYFORMAT_WRAP_FORMAT(void, format, /*empty*/, /*empty*/, out, /*empty*/)
#undef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS

// Define to nothing for format & printf; leave defined for convenience.
#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS

// std::string format(const char* fmt, const Args&... args);
TINYFORMAT_WRAP_FORMAT(std::string, format, /*empty*/,
                       std::ostringstream oss;, oss,
                       return oss.str();)

// void printf(const char* fmt, const Args&... args)
TINYFORMAT_WRAP_FORMAT(void, printf, /*empty*/, /*empty*/, std::cout, /*empty*/)

#endif

} // namespace tinyformat

#endif // TINYFORMAT_H_INCLUDED
