// bdlb_cstringhash.h                                                 -*-C++-*-
#ifndef INCLUDED_BDLB_CSTRINGHASH
#define INCLUDED_BDLB_CSTRINGHASH

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

//@PURPOSE: Provide a functor enabling C-strings as unordered-container keys.
//
//@CLASSES:
//  bdlb::CStringHash: functor enabling C-strings as unordered-container keys
//
//@SEE_ALSO:
//
//@DESCRIPTION: This component provides a 'struct', 'bdlb::CStringHash', that
// defines a functor to generate a hash code for a null-terminated string,
// rather than simply generating a hash code for the address of the string, as
// the 'std::hash' functor would do.  This hash functor is suitable for
// supporting C-strings as keys in unordered 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::CStringHash'
///- - - - - - - - - - - - - - - - - - - - - -
// Suppose we need an associative container to store some objects, uniquely
// identified by C-strings.   The following code illustrates how to use
// 'bdlb::CStringHash' as a hash function for the standard container
// 'unordered_map' taking C-string as a key.
//
// First, let us define our mapped type class:
//..
//  class Security
//  {
//      // This class implements a value semantic type that represents
//      // ownership of a security.
//
//      // DATA
//      char         *d_name_p;      // Security name
//      unsigned int  d_sharesOwned; // The number of owned shares
//
//    public:
//      // CREATORS
//      Security(const char *name, unsigned int sharesOwned);
//          // Create a 'Security' object having the specified 'name' and
//          // 'sharesOwned'.
//
//      Security(const Security& original);
//          // Create a 'Security' object having the value of the specified
//          // 'original' security.
//
//      ~Security();
//          // Destroy this security object.
//
//
//      // ACCESSORS
//      unsigned int sharesOwned() const;
//          // Return the value of the 'sharesOwned' attribute of this security
//          // object.
//
//      // MANIPULATORS
//      Security& operator=(Security other);
//          // Assign to this security object the value of the specified
//          // 'other' object, and return a reference providing modifiable
//          // access to this object.
//
//      void swap(Security& other);
//          // Efficiently exchange the value of this security with the value
//          // of the specified 'other' security.
//  };
//
//  // CREATORS
//  inline
//  Security::Security(const char *name, unsigned int sharesOwned)
//  : d_sharesOwned(sharesOwned)
//  {
//      d_name_p = new char [strlen(name) + 1];
//      strncpy(d_name_p, name, strlen(name) + 1);
//  }
//
//  inline
//  Security::Security(const Security& original)
//  : d_sharesOwned(original.d_sharesOwned)
//  {
//      if (this != &original)
//      {
//          d_name_p = new char [strlen(original.d_name_p) + 1];
//          strncpy(d_name_p,
//                  original.d_name_p,
//                  strlen(original.d_name_p) + 1);
//      }
//  }
//
//  inline
//  Security::~Security()
//  {
//      delete [] d_name_p;
//  }
//
//  // ACCESSORS
//
//  inline    unsigned int Security::sharesOwned() const
//  {
//      return d_sharesOwned;
//  }
//
//  // MANIPULATORS
//  inline
//  Security& Security::operator=(Security other)
//  {
//      this->swap(other);
//      return *this;
//  }
//
//  inline
//  void Security::swap(Security& other)
//  {
//      char * tempPtr = d_name_p;
//      d_name_p = other.d_name_p;
//      other.d_name_p = tempPtr;
//      unsigned int tempInt = d_sharesOwned;
//      d_sharesOwned = other.d_sharesOwned;
//      other.d_sharesOwned = tempInt;
//  }
//..
// Next, we define container type using 'bdlb::CStringHash' as a hash function
// and 'bdlb::CstringEqualTo' as a comparator:
//..
//  typedef unordered_map<const char *,
//                        Security,
//                        bdlb::CStringHash,
//                        bdlb::CStringEqualTo> SecuritiesUM;
//..
// This container stores objects of 'Security' class and allow access to them
// by their names.
//
// Then, we create several C-strings with security names:
//..
//  const char *ibm  = "IBM";
//  const char *msft = "Microsoft";
//  const char *goog = "Google";
//..
// Now, we create a container for securities and fill it:
//..
//  SecuritiesUM securities;
//
//  securities.insert(
//            std::make_pair<const char *, Security>(ibm, Security(ibm, 616)));
//  securities.insert(
//      std::make_pair<const char *, Security>(msft, Security(msft, 6150000)));
//..
// Finally, we make sure, that we able to access securities by their names:
//..
//  SecuritiesUM::iterator it = securities.find(ibm);
//  assert(616 == it->second.sharesOwned());
//  it = securities.find(msft);
//  assert(6150000 == it->second.sharesOwned());
//  it = securities.find(goog);
//  assert(securities.end() == it);
//..

#include <bdlscm_version.h>

#include <bslh_spookyhashalgorithm.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>
#include <bsl_cstddef.h>

namespace BloombergLP {
namespace bdlb {

                           // ==================
                           // struct CStringHash
                           // ==================

struct CStringHash {
    // This 'struct' defines a hash operation for null-terminated character
    // strings enabling them to be used as keys in the standard unordered
    // associative containers such as 'bsl::unordered_map' and
    // 'bsl::unordered_set'.  Note that this class is an empty POD type.

    // STANDARD TYPEDEFS
    typedef const char  *argument_type;
    typedef bsl::size_t  result_type;

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

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

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

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

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

    // ACCESSORS
    bsl::size_t operator()(const char *argument) const;
        // Return a hash code generated from the contents of the specified
        // null-terminated 'argument' string.  The behavior is undefined
        // unless 'argument' points to a null-terminated string.
};

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

                           // ------------------
                           // struct CStringHash
                           // ------------------

// ACCESSORS
inline
bsl::size_t bdlb::CStringHash::operator()(const char *argument) const
{
    BSLS_ASSERT(argument);

    bslh::SpookyHashAlgorithm hash;
    hash(argument, bsl::strlen(argument));
    return static_cast<bsl::size_t>(hash.computeHash());
}

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