// bdlb_caselessstringviewless.h                                      -*-C++-*-
#ifndef INCLUDED_BDLB_CASELESSSTRINGVIEWLESS
#define INCLUDED_BDLB_CASELESSSTRINGVIEWLESS

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

//@PURPOSE: Provide a case-insensitive less-than predicate for string views.
//
//@CLASSES:
//  bdlb::CaselessStringViewLess: a case-insensitive less for 'string_view's.
//
//@SEE_ALSO: bsl_map, bsl_set
//
//@DESCRIPTION: This component provides a 'struct',
// 'bdlb::CaselessStringViewLess', that defines a functor that compares two
// string views using a case-insensitive string comparison.  This
// lexicographical ordering makes 'CaselessStringViewLess' suitable for
// supporting 'bsl::string's or 'bsl::string_view's as keys in case-insensitive
// ordered associative containers.
//
// Note that using this component to compare keys in a container is less
// efficient than converting them all to the same case prior to insertion and
// then just doing straight string compares.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Basic Use of 'bdlb::CaselessStringViewLess'
/// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Suppose we need a container to store set of unique strings.  The following
// code illustrates how to use 'bdlb::CaselessStringViewLess' as a comparator
// for the standard container 'set', to create a set of unique case-insensitive
// string values.
//
// First, we create several strings:
//..
//  const bsl::string newYork        = "NY";
//  const bsl::string losAngeles     = "LA";
//  const bsl::string newJersey      = "NJ";
//  const bsl::string sanFrancisco   = "SF";
//  const bsl::string anotherNewYork = "ny";
//..
// Next, we create two containers, one with default comparator and another
// using 'bdlb::CstringLess' as a comparator:
//..
//  bsl::set<bsl::string>                               caseSensitiveSet;
//  bsl::set<bsl::string, bdlb::CaselessStringViewLess> caseInsensitiveSet;
//..
// Then, we fill containers with the same contents:
//..
//  caseSensitiveSet.insert(newYork);
//  caseSensitiveSet.insert(losAngeles);
//  caseSensitiveSet.insert(newJersey);
//  caseSensitiveSet.insert(sanFrancisco);
//  caseSensitiveSet.insert(anotherNewYork);
//
//  caseInsensitiveSet.insert(newYork);
//  caseInsensitiveSet.insert(losAngeles);
//  caseInsensitiveSet.insert(newJersey);
//  caseInsensitiveSet.insert(sanFrancisco);
//  caseInsensitiveSet.insert(anotherNewYork);
//..
// Next, we observe that the container created with 'CaselessStringViewLess'
// ('caseInsensitiveSet') contains the correct number of unique string values
// (4), while the container using the default comparator does not:
//..
//  assert(5 == caseSensitiveSet.size());
//  assert(4 == caseInsensitiveSet.size());
//..
// Now, we observe the members of the case-sensitive set:
//..
//  assert( caseSensitiveSet.count("NY"));
//  assert(!caseSensitiveSet.count("nY"));
//  assert(!caseSensitiveSet.count("Ny"));
//  assert( caseSensitiveSet.count("ny"));
//
//  assert( caseSensitiveSet.count("SF"));
//  assert(!caseSensitiveSet.count("sF"));
//  assert(!caseSensitiveSet.count("Sf"));
//  assert(!caseSensitiveSet.count("sf"));
//..
// Finally, we observe that we can do case-insensitive access to
// 'caseInsensiveSet':
//..
//  assert( caseInsensitiveSet.count("NY"));
//  assert( caseInsensitiveSet.count("nY"));
//  assert( caseInsensitiveSet.count("Ny"));
//  assert( caseInsensitiveSet.count("ny"));
//
//  assert( caseInsensitiveSet.count("LA"));
//  assert( caseInsensitiveSet.count("lA"));
//  assert( caseInsensitiveSet.count("La"));
//  assert( caseInsensitiveSet.count("la"));
//
//  assert( caseInsensitiveSet.count("nj"));
//  assert( caseInsensitiveSet.count("nJ"));
//  assert( caseInsensitiveSet.count("Nj"));
//  assert( caseInsensitiveSet.count("NJ"));
//
//  assert( caseInsensitiveSet.count("sf"));
//  assert( caseInsensitiveSet.count("sF"));
//  assert( caseInsensitiveSet.count("Sf"));
//  assert( caseInsensitiveSet.count("SF"));
//
//  assert(!caseInsensitiveSet.count("GA"));
//  assert(!caseInsensitiveSet.count("gA"));
//  assert(!caseInsensitiveSet.count("Ga"));
//  assert(!caseInsensitiveSet.count("ga"));
//..

#include <bdlscm_version.h>

#include <bdlb_stringviewutil.h>

#include <bslmf_istriviallycopyable.h>
#include <bslmf_istriviallydefaultconstructible.h>
#include <bslmf_nestedtraitdeclaration.h>

#include <bsls_assert.h>

#include <bsl_algorithm.h>
#include <bsl_cstddef.h>
#include <bsl_string_view.h>

namespace BloombergLP {
namespace bdlb {

                        // =============================
                        // struct CaselessStringViewLess
                        // =============================

struct CaselessStringViewLess {
    // This 'struct' defines an ordering on string views, enabling them for use
    // as keys in the standard associative containers such as 'bsl::map' and
    // 'bsl::set'.  Note that this class is an empty POD type.

    // PUBLIC TYPES
    typedef bsl::string_view first_argument_type;
    typedef bsl::string_view second_argument_type;
    typedef bool             result_type;
    typedef void             is_transparent;
        // Type alias indicating this is a transparent hash functor.

    // TRAITS
    BSLMF_NESTED_TRAIT_DECLARATION(CaselessStringViewLess,
                                   bsl::is_trivially_copyable);
    BSLMF_NESTED_TRAIT_DECLARATION(CaselessStringViewLess,
                                   bsl::is_trivially_default_constructible);

    // CREATORS
    //! CaselessStringViewLess() = default;
        // Create a 'CaselessStringViewLess' object.

    //! CaselessStringViewLess(const CaselessStringViewLess& original) =
    //                                                                 default;
        // Create a 'CaselessStringViewLess' object.  Note that as
        // 'CaselessStringViewLess' is an empty (stateless) type, this
        // operation has no observable effect.

    //! ~CaselessStringViewLess() = default;
        // Destroy this object.

    // MANIPULATORS
    //! CaselessStringViewLess& operator=(const CaselessStringViewLess& rhs) =
    //                                                                 default;
        // Assign to this object the value of the specified 'rhs' object, and
        // return a reference providing modifiable access to this object.  Note
        // that as 'CaselessStringViewLess' is an empty (stateless) type, this
        // operation has no observable effect.

    // ACCESSORS
    bool operator()(bsl::string_view lhs, bsl::string_view rhs) const;
        // Return 'true' if the specified 'lhs' is lexicographically ordered
        // before the specified 'rhs', and 'false' otherwise.
};

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

                        // -----------------------------
                        // struct CaselessStringViewLess
                        // -----------------------------

// ACCESSORS
inline
bool CaselessStringViewLess::operator()(bsl::string_view lhs,
                                        bsl::string_view rhs) const
{
    return bdlb::StringViewUtil::lowerCaseCmp(lhs, rhs) < 0;
}

}  // close package namespace
}  // close enterprise namespace

#endif

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