// 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_CPP17_BASELINE_LIBRARY
   using std::quoted;
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY

}  // close namespace bsl

namespace BloombergLP {
namespace bslstl {
#if defined BSLS_LIBRARYFEATURES_HAS_CPP17_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
                    // ===================================

/// 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.
template <class t_CHAR_TYPE, class t_CHAR_TRAITS, class t_ALLOC>
class IoManip_QuotedStringFormatter {

    // DATA

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

    // delimiter
    t_CHAR_TYPE                                             d_delim;

    // escape character
    t_CHAR_TYPE                                             d_escape;

  public:
    // CREATORS

    /// Create an object pointing to the specified `str` and having the
    /// optionally specified `delim` and `escape` characters.
    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('\\'));

    // ACCESSORS

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

    /// Return the escape character.
    t_CHAR_TYPE escape() 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).
    bsl::basic_string<t_CHAR_TYPE, t_CHAR_TRAITS, t_ALLOC> *str() const;
};

                  // =======================================
                  // 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.
template <class t_CHAR_TYPE, class t_CHAR_TRAITS>
class IoManip_QuotedStringViewFormatter {

    // 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

    /// Create an object having the value of the specified `strView` and the
    /// optionally specified `delim` and `escape` characters.
    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('\\'));

    // ACCESSORS

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

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

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

// FREE FUNCTIONS

/// 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_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);

/// Write the value of the specified `object` to the specified `output`
/// stream.
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);

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

namespace bsl {
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
/// 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 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>
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 (or extracted from input) stream.
/// 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.
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('\\'));

#ifndef BSLSTL_STRING_VIEW_IS_ALIASED
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  // not BSLSTL_STRING_VIEW_IS_ALIASED
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY
}  // close namespace bsl

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

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_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 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 BloombergLP::bslstl::IoManip_QuotedStringFormatter<t_CHAR_TYPE,
                                                              t_CHAR_TRAITS,
                                                              t_ALLOC>(&value,
                                                                       delim,
                                                                       escape);
}

#ifndef BSLSTL_STRING_VIEW_IS_ALIASED
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  // not BSLSTL_STRING_VIEW_IS_ALIASED
#endif  // BSLS_LIBRARYFEATURES_HAS_CPP17_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 ----------------------------------
