// bdlb_cstringless.h                                                 -*-C++-*-
#ifndef INCLUDED_BDLB_CSTRINGLESS
#define INCLUDED_BDLB_CSTRINGLESS

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

//@PURPOSE: Provide a standard compatible less-than predicate for C-strings.
//
//@CLASSES:
//  bdlb::CStringLess: a standard compatible less-than predicate for C-strings.
//
//@SEE_ALSO: bsl_map, bsl_set
//
//@DESCRIPTION: This component provides a `struct`, `bdlb::CStringLess`, that
// defines a functor that compares two null-terminated strings using a
// case-sensitive string comparison, rather than simply comparing the two
// addresses (as the `std::less` functor would do).  This lexicographical
// ordering makes `CStringLess` suitable for supporting C-strings as keys in
// associative containers.  Note that the container behavior would be undefined
// if the strings referenced by such pointers were to change value.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Basic Use of `bdlb::CStringLess`
///- - - - - - - - - - - - - - - - - - - - - -
// Suppose we need a container to store set of unique C-strings. The following
// code illustrates how to use `bdlb::CStringLess` as a comparator for the
// standard container `set`, to create a set of unique C-string values.
//
// Note that the default comparator for `const char *` (i.e.,
// `bsl::less<const char *>`) compares the supplied addresses, rather than the
// contents of the C-strings to which those address typically refer.  As a
// result, when using the default comparator, identical C-string values located
// at different addresses, will be successfully added to a `set` container.
// `bdlb::CStringLess` compares the values of the C-strings ensuring that a
// `set`, using `CstringLess` as a comparator, is a set of unique string
// values.
//
// First, we create several C-strings:
// ```
// const char newYork[]        = "NY";
// const char losAngeles[]     = "LA";
// const char newJersey[]      = "NJ";
// const char sanFrancisco[]   = "SF";
// const char anotherNewYork[] = "NY";
// ```
// Next, we create two containers, one with default comparator and another
// using `bdlb::CstringLess` as a comparator:
// ```
// bsl::set<const char *>                    defaultComparatorContainer;
// bsl::set<const char *, bdlb::CStringLess> userComparatorContainer;
// ```
// Now, we fill containers with the same contents:
// ```
// defaultComparatorContainer.insert(newYork);
// defaultComparatorContainer.insert(losAngeles);
// defaultComparatorContainer.insert(newJersey);
// defaultComparatorContainer.insert(sanFrancisco);
// defaultComparatorContainer.insert(anotherNewYork);
//
// userComparatorContainer.insert(newYork);
// userComparatorContainer.insert(losAngeles);
// userComparatorContainer.insert(newJersey);
// userComparatorContainer.insert(sanFrancisco);
// userComparatorContainer.insert(anotherNewYork);
// ```
// Finally, we observe that the container created with `CStringLess`
// (`userComparatorContainer`) contains the correct number of unique C-string
// values (4), while the container using the default comparator does not:
// ```
// assert(5 == defaultComparatorContainer.size());
// assert(4 == userComparatorContainer.size());
// ```

#include <bdlscm_version.h>

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

#include <bsls_assert.h>
#include <bsls_review.h>

#include <bsl_cstring.h>

namespace BloombergLP {
namespace bdlb {

                        // ==================
                        // struct CStringLess
                        // ==================

/// This `struct` defines an ordering on null-terminated character strings,
/// 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.
struct CStringLess {

    // STANDARD TYPEDEFS
    typedef const char *first_argument_type;
    typedef const char *second_argument_type;
    typedef bool result_type;

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

    // CREATORS

    /// Create a `CStringLess` object.
    //! CStringLess() = default;

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

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

    // MANIPULATORS

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

    // ACCESSORS

    /// Return `true` if the specified `lhs` string is lexicographically
    /// ordered before the specified `rhs` string, and `false` otherwise.
    /// The behavior is undefined unless both `lhs` and `rhs` point to
    /// null-terminated strings.
    bool operator()(const char *lhs, const char *rhs) const;
};

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

                          // ------------------
                          // struct CStringLess
                          // ------------------

// ACCESSORS
inline
bool CStringLess::operator()(const char *lhs, const char *rhs) const
{
    BSLS_ASSERT(lhs);
    BSLS_ASSERT(rhs);

    return bsl::strcmp(lhs, rhs) < 0;
}

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

#endif

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