/* /////////////////////////////////////////////////////////////////////////
 * Namespace
 */
#if !defined(PANTHEIOS_NO_NAMESPACE)
namespace pantheios
{
#endif /* !PANTHEIOS_NO_NAMESPACE */
/* /////////////////////////////////////////////////////////////////////////
 * Inserter classes
 */
/** Class for inserting argc+argv arguments into Pantheios
 *    diagnostic logging statements.
 *
 * \ingroup group__application_layer_interface__inserters
 *
 * This class formats an argc+argv pair into a string to
 * be inserted into a logging statement.
 *
 * By default, arguments that contain spaces (TAB or space character) will
 * be enclosed in double quotes, and those that do not will not. This
 * behaviour can be moderated by use of the
 * \link pantheios::args::neverQuoteArgs args::neverQuoteArgs\endlink
 * and
 * \link pantheios::args::alwaysQuoteArgs args::alwaysQuoteArgs\endlink
 * member constants.
 *
 * Consider the following statement:
 * \code
  int main(int argc, char* argv[])
  {
    pantheios::log_DEBUG("main(", args(argc, argv), ")");
    . . .
 * \endcode
 *
 * Suppose the program is /test/myprog and the command-line
 * arguments are abc, -123 and
 * Billy Jean. This will produce the output:
\htmlonly
   /test/myprog, abc, -123, "Billy Jean"
\endhtmlonly
 *
 * We may specify different flags from the default
 * (\link pantheios::args::quoteArgsWithSpaces args::quoteArgsWithSpaces\endlink)
 * in the third constructor argument, as in:
 * \code
  int main(int argc, char* argv[])
  {
    pantheios::log_DEBUG("main(", pantheios::args(argc, argv, pantheios::args::neverQuoteArgs), ")");
    . . .
 * \endcode
 *
 * Using the same arguments, this will produce the output:
\htmlonly
   /test/myprog, abc, -123, Billy Jean
\endhtmlonly
 *
 */
class args
{
/// \name Member Types
/// @{
public:
    typedef args    class_type;
/// @}
/// \name Member Constants
/// @{
public:
    ///  The format flags
    enum format_flags
    {
            neverQuoteArgs      =   0x0000  /*!< arguments are never quoted */
        ,   quoteArgsWithSpaces =   0x0001  /*!< arguments are quoted if they contain spaces */
        ,   alwaysQuoteArgs     =   0x0002  /*!< arguments are always quoted */
        ,   arg0FileOnly        =   0x0004  /*!< causes only the file part of arg0 to be displayed */
    };
/// @}
/// \name Construction
/// @{
public:
    ///  Constructs an \link pantheios::args args\endlink inserter
    ///   that will display the command-line arguments.
    ///
    /// \param argc The number of arguments in the argument array.
    /// \param argv The array of arguments.
    /// \param flags \link pantheios::args::format_flags Flags\endlink that
    ///   control the formatting of the shim.
    /// \param separator String used to separate multiple arguments; defaults to ", "
    args(int argc, pan_char_t const* const* argv, int flags = quoteArgsWithSpaces, pan_char_t const* separator = PANTHEIOS_LITERAL_STRING(", "));
#ifdef STLSOFT_COMPILER_IS_BORLAND
    args(int argc, pan_char_t** argv, int flags = quoteArgsWithSpaces, pan_char_t const* separator = PANTHEIOS_LITERAL_STRING(", "));
#endif /* STLSOFT_COMPILER_IS_BORLAND */
#ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
    ~args() stlsoft_throw_0();
#endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
/// @}
/// \name Accessors
/// @{
public:
    ///  A possibly non-nul-terminated non-null pointer to the c-style string representation of the integer
    pan_char_t const*   data() const;
    ///  A nul-terminated non-null pointer to the c-style string representation of the integer
    pan_char_t const*   c_str() const;
    ///  The size of the c-style string representation of the integer
    size_t              size() const;
/// @}
/// \name Implementation
/// @{
private:
    void construct_() const;
    void construct_();
/// @}
/// \name Member Variables
/// @{
private:
    typedef std::basic_string string_type_;
    const int                   m_flags;
    const int                   m_argc;
    pan_char_t const* const*    m_argv;
    const string_type_          m_separator;
    string_type_                m_result;
/// @}
/// \name Not to be implemented
/// @{
private:
#if !defined(STLSOFT_COMPILER_IS_GCC)
    args(class_type const&);
#endif /* compiler */
    class_type& operator =(class_type const&);
/// @}
};
/* /////////////////////////////////////////////////////////////////////////
 * String Access Shims
 */
#ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
# if !defined(PANTHEIOS_NO_NAMESPACE)
namespace shims
{
# endif /* !PANTHEIOS_NO_NAMESPACE */
/** \overload c_str_data_a(args const&) */
# ifdef PANTHEIOS_USE_WIDE_STRINGS
inline wchar_t const* c_str_data_w(args const& a)
{
    return a.data();
}
# else /* ? PANTHEIOS_USE_WIDE_STRINGS */
inline char const* c_str_data_a(args const& a)
{
    return a.data();
}
# endif /* PANTHEIOS_USE_WIDE_STRINGS */
/** \overload c_str_data(args const&) */
inline pan_char_t const* c_str_data(args const& a)
{
    return a.data();
}
/** \overload c_str_len_a(args const&) */
# ifdef PANTHEIOS_USE_WIDE_STRINGS
inline size_t c_str_len_w(args const& a)
# else /* ? PANTHEIOS_USE_WIDE_STRINGS */
inline size_t c_str_len_a(args const& a)
# endif /* PANTHEIOS_USE_WIDE_STRINGS */
{
    return a.size();
}
/** \overload c_str_len(args const&) */
inline size_t c_str_len(args const& a)
{
    return a.size();
}
/** \overload c_str_ptr_a(args const&) */
# ifdef PANTHEIOS_USE_WIDE_STRINGS
inline wchar_t const* c_str_ptr_w(args const& a)
{
    return a.c_str();
}
# else /* ? PANTHEIOS_USE_WIDE_STRINGS */
inline char const* c_str_ptr_a(args const& a)
{
    return a.c_str();
}
# endif /* PANTHEIOS_USE_WIDE_STRINGS */
/** \overload c_str_ptr(args const&) */
inline pan_char_t const* c_str_ptr(args const& a)
{
    return a.c_str();
}
# if !defined(PANTHEIOS_NO_NAMESPACE)
} /* namespace shims */
#  if defined(STLSOFT_COMPILER_IS_GCC)
    /* GCC does not seem to correctly handle the phases of
     * processing of C++ templates, so we need to 'use' the
     * shims into the same namespace as the inserter class
     * in order that ADL can suffice instead.
     */
#   ifdef PANTHEIOS_USE_WIDE_STRINGS
    using ::pantheios::shims::c_str_data_w;
    using ::pantheios::shims::c_str_len_w;
    using ::pantheios::shims::c_str_ptr_w;
#   else /* ? PANTHEIOS_USE_WIDE_STRINGS */
    using ::pantheios::shims::c_str_data_a;
    using ::pantheios::shims::c_str_len_a;
    using ::pantheios::shims::c_str_ptr_a;
#   endif /* PANTHEIOS_USE_WIDE_STRINGS */
    using ::pantheios::shims::c_str_data;
    using ::pantheios::shims::c_str_len;
    using ::pantheios::shims::c_str_ptr;
#  endif /* compiler */
# endif /* !PANTHEIOS_NO_NAMESPACE */
#endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
/* /////////////////////////////////////////////////////////////////////////
 * Namespace
 */
#if !defined(PANTHEIOS_NO_NAMESPACE)
} /* namespace pantheios */
namespace stlsoft
{
    // 'Export' the string access shims into the STLSoft namespace
    //
    // c_str_ptr(_a) is not necessary for version 1.0 of Pantheios, but it's
    // defined and exported in order to allow for the case where someone
    // may find a legitimate use for the conversion classes additional to
    // the type-tunneling of the Pantheios API.
# ifdef PANTHEIOS_USE_WIDE_STRINGS
    using ::pantheios::shims::c_str_data_w;
    using ::pantheios::shims::c_str_len_w;
    using ::pantheios::shims::c_str_ptr_w;
# else /* ? PANTHEIOS_USE_WIDE_STRINGS */
    using ::pantheios::shims::c_str_data_a;
    using ::pantheios::shims::c_str_len_a;
    using ::pantheios::shims::c_str_ptr_a;
# endif /* PANTHEIOS_USE_WIDE_STRINGS */
    using ::pantheios::shims::c_str_data;
    using ::pantheios::shims::c_str_len;
    using ::pantheios::shims::c_str_ptr;
}
#endif /* !PANTHEIOS_NO_NAMESPACE */
/* /////////////////////////////////////////////////////////////////////////
 * Inclusion
 */
#ifdef STLSOFT_PPF_pragma_once_SUPPORT
# pragma once
#endif /* STLSOFT_PPF_pragma_once_SUPPORT */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* !PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_ARGS */
/* ///////////////////////////// end of file //////////////////////////// */