// bslstl_iomanip.h                                                   -*-C++-*-
#ifndef INCLUDED_BSLSTL_IOMANIP
#define INCLUDED_BSLSTL_IOMANIP

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide BSL implementations for standard <iomanip> features.
//
//@CLASSES:
//
//@CANONICAL_HEADER: bsl_iomanip.h
//
//@SEE_ALSO: bsl+bslhdrs
//

//@DESCRIPTION: This component is for internal use only.  Please include
// '<bsl_iomanip.h>' instead.
//
// This component exists to provide BSL implementations for facilities in the
// standard <iomanip> header.  While most of the facilities in 'bsl_iomanip.h'
// are simply aliases to the platform standard library, some of them need BSL
// specific implementations.  For example, this component provides
// implementations for 'bsl::quoted' overloads that accept 'bsl::basic_string'
// and proprietary 'bsl::string_view' objects.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Basic Use of 'bsl::quoted'
///- - - - - - - - - - - - - - - - - - -
// Suppose we want to serialize some data into JSON.
//
// First, we define a struct, 'Employee', to contain the data:
//..
//  struct Employee {
//      bsl::string d_firstName;
//      bsl::string d_lastName;
//      int         d_age;
//  };
//..
// Then, we create an 'Employee' object and populate it with data:
//..
//  Employee john;
//  john.d_firstName = "John";
//  john.d_lastName  = "Doe";
//  john.d_age       = 20;
//..
//  Now, we create an output stream and manually construct the JSON string
//  using 'bsl::quoted':
//..
//  bsl::stringstream ss;
//  ss << '{' << '\n';
//  ss << bsl::quoted("firstName");
//  ss << ':';
//  ss << bsl::quoted(john.d_firstName);
//  ss << ',' << '\n';
//  ss << bsl::quoted("lastName");
//  ss << ':';
//  ss << bsl::quoted(john.d_lastName);
//  ss << ',' << '\n';
//  ss << bsl::quoted("age");
//  ss << ':';
//  ss << john.d_age;
//  ss << '\n' << '}';
//..
//  Finally, we check out the JSON string:
//..
//  bsl::string expected = "{\n"
//                         "\"firstName\":\"John\",\n"
//                         "\"lastName\":\"Doe\",\n"
//                         "\"age\":20\n"
//                         "}";
//  assert(expected == ss.str());
//..
//  The output should look like:
//..
//  {
//  "firstName":"John",
//  "lastName":"Doe",
//  "age":20
//  }
//..

#include <bslstl_string.h>
#include <bslstl_stringview.h>

#include <bsls_libraryfeatures.h>
#include <bsls_platform.h>

#include <iomanip>
#include <istream>
#include <ostream>

namespace bsl {
    // Import selected symbols into bsl namespace

    using std::resetiosflags;
    using std::setbase;
    using std::setfill;
    using std::setiosflags;
    using std::setprecision;
    using std::setw;

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
    using std::get_money;
    using std::put_money;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_MISCELLANEOUS_UTILITIES
    using std::get_time;
    using std::put_time;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP11_MISCELLANEOUS_UTILITIES

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
    // Export additional names, leaked to support transitive dependencies in
    // higher level (non BDE) Bloomberg code.
# if !defined(BSLS_PLATFORM_CMP_MSVC) && __cplusplus < 201703L
    // As some of these names are removed from C++17, take a sledgehammer to
    // crack this nut, and remove all non-standard exports.
    using std::bad_exception;
    using std::basic_ios;
    using std::basic_iostream;
    using std::basic_istream;
    using std::basic_ostream;
    using std::basic_streambuf;
    using std::bidirectional_iterator_tag;
    using std::ctype;
    using std::ctype_base;
    using std::ctype_byname;
    using std::exception;
    using std::forward_iterator_tag;
    using std::input_iterator_tag;
    using std::ios_base;
    using std::istreambuf_iterator;
    using std::iterator;
    using std::locale;
    using std::num_get;
    using std::numpunct;
    using std::numpunct_byname;
    using std::ostreambuf_iterator;
    using std::output_iterator_tag;
    using std::random_access_iterator_tag;
    using std::set_terminate;
    using std::set_unexpected;
    using std::swap;
    using std::terminate;
    using std::terminate_handler;
    using std::uncaught_exception;
    using std::unexpected;
    using std::unexpected_handler;
    using std::use_facet;
# endif // MSVC, or C++2017
#endif  // BDE_OMIT_INTERNAL_DEPRECATED

#if defined BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
   using std::quoted;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY

}  // close namespace bsl

namespace BloombergLP {
namespace bslstl {
#if defined BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
// 'std::quoted' function does not support the 'bsl::basic_string' and
// proprietary implementation of the 'bsl::basic_string_view' classes.  To fix
// this we need to add special overloads that return objects of the special
// classes, that can be used in stream input/output operations and construct a
// bridge between 'std' and 'bsl' 'string'/'string_view' implementations.

                    // ===================================
                    // class IoManip_QuotedStringFormatter
                    // ===================================

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
class IoManip_QuotedStringFormatter {
    // Private class: do not use outside of 'bslstl_iomanip.h' header.  This
    // private class provides a temporary storage that can be extracted to/from
    // a stream and provides data to the standard implementation of the
    // 'quoted' function.  Note that this class does not contain the storage
    // itself, but only points to an external object.  Note that
    // 'QuotedStringViewFormatter' is designed so that its objects are returned
    // as temporary objects (of opaque type) from 'bsl::quoted`, and then
    // passed to a streaming operator; it serves as a temporary proxy for a
    // string value.

    // DATA
    bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *d_str_p;
        // string for quoting (held, not owned)

    t_CHAR_TYPE                                             d_delim;
        // delimiter

    t_CHAR_TYPE                                             d_escape;
        // escape character

  public:
    // CREATORS
    explicit IoManip_QuotedStringFormatter(
               bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *str,
               t_CHAR_TYPE                                             delim =
                                                              t_CHAR_TYPE('"'),
               t_CHAR_TYPE                                             escape =
                                                            t_CHAR_TYPE('\\'));
        // Create an object pointing to the specified 'str' and having the
        // optionally specified 'delim' and 'escape' characters.

    // ACCESSORS
    t_CHAR_TYPE delim() const;
        // Return the delimiter character.

    t_CHAR_TYPE escape() const;
        // Return the escape character.

    bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *str() const;
        // Return a reference providing modifiable access to the underlying
        // string.  Note that this operation provides modifiable access to the
        // string because this type is designed so that its objects are created
        // as temporary objects that proxy an underlying string (see class
        // documentation).
};

                  // =======================================
                  // class IoManip_QuotedStringViewFormatter
                  // =======================================

template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
class IoManip_QuotedStringViewFormatter {
    // Private class: do not use outside of 'bslstl_iomanip.h' header.  This
    // private class provides a temporary storage that can be extracted to a
    // stream and provides data to the standard implementation of the 'quoted'
    // function.  Note that 'QuotedStringViewFormatter' is designed to be
    // returned as a temporary object (of opaque type) from 'bsl::quoted`, and
    // passed to a streaming operator; it serves as a temporary proxy for a
    // string value.  Also note that this value is copied to 'bsl::string' data
    // member that is owned by the object of this class.

    // DATA
    bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS> d_str;     // string for
                                                             // quoting

    t_CHAR_TYPE                                   d_delim;   // delimiter

    t_CHAR_TYPE                                   d_escape;  // escape
                                                             // character

  public:
    // CREATORS
    explicit IoManip_QuotedStringViewFormatter(
             const bsl::basic_string_view<t_CHAR_TYPE, t_CHAR_TRAITS>& strView,
             t_CHAR_TYPE                                               delim =
                                                              t_CHAR_TYPE('"'),
             t_CHAR_TYPE                                               escape =
                                                            t_CHAR_TYPE('\\'));
        // Create an object having the value of the specified 'strView' and the
        // optionally specified 'delim' and 'escape' characters.

    // ACCESSORS
    const t_CHAR_TYPE *data() const;
        // Return a reference providing modifiable access to the character
        // buffer of the underlying string.

    t_CHAR_TYPE delim() const;
        // Return the delimiter character.

    t_CHAR_TYPE escape() const;
        // Return the escape character.
};

// FREE FUNCTIONS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
std::basic_istream<t_CHAR_TYPE, t_CHAR_TRAITS>& operator>>(
                       std::basic_istream<t_CHAR_TYPE, t_CHAR_TRAITS>& input,
                       const IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                           t_CHAR_TRAITS,
                                                           t_ALLOC>&   object);
    // Read quoted string from the specified 'input' stream into the underlying
    // string of the specified 'object'.  Note that the 'object' here is
    // 'const' because the 'QuotedStringFormatter' is designed to be returned
    // as a temporary object from 'bsl::quoted`, serving as a proxy for the
    // underlying string.

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>& operator<<(
                       std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>& output,
                       const IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                           t_CHAR_TRAITS,
                                                           t_ALLOC>&   object);
    // Write the value of the specified 'object' to the specified 'output'
    // stream.

template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>& operator<<(
               std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>&         output,
               const IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>& object);
    // Write the value of the specified 'object' to the specified 'output'
    // stream.

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
}  // close package namespace
}  // close enterprise namespace

namespace bsl {
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
decltype(auto)
quoted(const bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC>& value,
       t_CHAR_TYPE                                                   delim =
                                                              t_CHAR_TYPE('"'),
       t_CHAR_TYPE                                                   escape =
                                                            t_CHAR_TYPE('\\'));
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output stream.

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                    t_CHAR_TRAITS,
                                                   t_ALLOC>
quoted(bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC>& value,
       t_CHAR_TYPE                                             delim =
                                                              t_CHAR_TYPE('"'),
       t_CHAR_TYPE                                             escape =
                                                            t_CHAR_TYPE('\\'));
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output (or extracted from input) stream.

#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>
quoted(const bsl::basic_string_view<t_CHAR_TYPE, t_CHAR_TRAITS>& value,
       t_CHAR_TYPE                                               delim =
                                                              t_CHAR_TYPE('"'),
       t_CHAR_TYPE                                               escape =
                                                            t_CHAR_TYPE('\\'));
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output stream.
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
}  // close namespace bsl

// ============================================================================
//                         INLINE FUNCTION DEFINITIONS
// ============================================================================

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY
                    // -----------------------------------
                    // class IoManip_QuotedStringFormatter
                    // -----------------------------------

// CREATORS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
inline
BloombergLP::bslstl::
    IoManip_QuotedStringFormatter<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC>::
        IoManip_QuotedStringFormatter(
                bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *str,
                t_CHAR_TYPE                                             delim,
                t_CHAR_TYPE                                             escape)
: d_str_p(str)
, d_delim(delim)
, d_escape(escape)
{
}

// ACCESSORS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
inline
t_CHAR_TYPE
BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                   t_CHAR_TRAITS,
                                                   t_ALLOC>::delim() const
{
    return d_delim;
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
inline
t_CHAR_TYPE
BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                   t_CHAR_TRAITS,
                                                   t_ALLOC>::escape() const
{
    return d_escape;
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
inline
bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *
BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                   t_CHAR_TRAITS,
                                                   t_ALLOC>::str() const
{
    return d_str_p;
}

                  // ---------------------------------------
                  // class IoManip_QuotedStringViewFormatter
                  // ---------------------------------------

// CREATORS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
inline
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>::
    IoManip_QuotedStringViewFormatter(
             const bsl::basic_string_view<t_CHAR_TYPE, t_CHAR_TRAITS>& strView,
             t_CHAR_TYPE                                               delim,
             t_CHAR_TYPE                                               escape)
: d_str(strView)
, d_delim(delim)
, d_escape(escape)
{
}

// ACCESSORS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
inline
const t_CHAR_TYPE *
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>::data()
    const
{
    return d_str.c_str();
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
inline
t_CHAR_TYPE
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>::delim()
    const
{
    return d_delim;
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
inline
t_CHAR_TYPE
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>::escape()
    const
{
    return d_escape;
}

// FREE FUNCTIONS
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
std::basic_istream<t_CHAR_TYPE, t_CHAR_TRAITS>&
BloombergLP::bslstl::operator>>(
                        std::basic_istream<t_CHAR_TYPE, t_CHAR_TRAITS>& input,
                        const IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                            t_CHAR_TRAITS,
                                                            t_ALLOC>&   object)
{
    std::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS> temp;
    input >> std::quoted(temp, object.delim(), object.escape());
    *object.str() = temp;
    return input;
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>&
BloombergLP::bslstl::operator<<(
                        std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>& output,
                        const IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                            t_CHAR_TRAITS,
                                                            t_ALLOC>&   object)
{
    output << std::quoted(object.str()->c_str(),
                          object.delim(),
                          object.escape());
    return output;
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>&
BloombergLP::bslstl::operator<<(
   std::basic_ostream<t_CHAR_TYPE, t_CHAR_TRAITS>&                      output,
   const IoManip_QuotedStringViewFormatter<t_CHAR_TYPE, t_CHAR_TRAITS>& object)
{
    output << std::quoted(object.data(), object.delim(), object.escape());
    return output;
}

                       // -----------------------------
                       // 'bsl::quoted' implementations
                       // -----------------------------

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
decltype(auto)
bsl::quoted(
          const bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC>& value,
          t_CHAR_TYPE                                                   delim,
          t_CHAR_TYPE                                                   escape)
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output stream.
{
    return bsl::quoted(value.c_str(), delim, escape);
}

template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                   t_CHAR_TRAITS,
                                                   t_ALLOC>
bsl::quoted(bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC>& value,
            t_CHAR_TYPE                                             delim,
            t_CHAR_TYPE                                             escape)
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output (or extracted from input) stream.
{
    return BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                              t_CHAR_TRAITS,
                                                              t_ALLOC>(&value,
                                                                       delim,
                                                                       escape);
}

#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<t_CHAR_TYPE,
                                                       t_CHAR_TRAITS>
bsl::quoted(const bsl::basic_string_view<t_CHAR_TYPE, t_CHAR_TRAITS>& value,
            t_CHAR_TYPE                                               delim,
            t_CHAR_TYPE                                               escape)
    // Return an object, containing quoted version of the specified 'value'
    // obtained using the optionally specified 'delim' and 'escape' characters,
    // and that can be inserted to output stream.
{
    return BloombergLP::bslstl::IoManip_QuotedStringViewFormatter<
                                                        t_CHAR_TYPE,
                                                        t_CHAR_TRAITS>(value,
                                                                       delim,
                                                                       escape);
}
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_BASELINE_LIBRARY

#endif

// ----------------------------------------------------------------------------
// Copyright 2022 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------