// Copyright 2005 Google Inc.
//
// #status: RECOMMENDED
// #category: maps
// #summary: Utility functions for use with map-like containers.
//
// This file provides utility functions for use with STL map-like data
// structures, such as std::map and hash_map. Some functions will also work with
// sets, such as ContainsKey().
//
// The main functions in this file fall into the following categories:
//
// - Find*()
// - Contains*()
// - Insert*()
// - Lookup*()
//
// These functions often have "...OrDie" or "...OrDieNoPrint" variants. These
// variants will crash the process with a CHECK() failure on error, including
// the offending key/data in the log message. The NoPrint variants will not
// include the key/data in the log output under the assumption that it's not a
// printable type.
//
// Most functions are fairly self explanatory from their names, with the
// exception of Find*() vs Lookup*(). The Find functions typically use the map's
// .find() member function to locate and return the map's value type. The
// Lookup*() functions typically use the map's .insert() (yes, insert) member
// function to insert the given value if necessary and returns (usually a
// reference to) the map's value type for the found item.
//
// See the per-function comments for specifics.
//
// There are also a handful of functions for doing other miscellaneous things.
//
// A note on terminology:
//
// Map-like containers are collections of pairs. Like all STL containers they
// contain a few standard typedefs identifying the types of data they contain.
// Given the following map declaration:
//
//   map<string, int> my_map;
//
// the notable typedefs would be as follows:
//
//   - key_type    -- string
//   - value_type  -- pair<const string, int>
//   - mapped_type -- int
//
// Note that the map above contains two types of "values": the key-value pairs
// themselves (value_type) and the values within the key-value pairs
// (mapped_type). A value_type consists of a key_type and a mapped_type.
//
// The documentation below is written for programmers thinking in terms of keys
// and the (mapped_type) values associated with a given key.  For example, the
// statement
//
//   my_map["foo"] = 3;
//
// has a key of "foo" (type: string) with a value of 3 (type: int).
//

#ifndef UTIL_GTL_MAP_UTIL_H_
#define UTIL_GTL_MAP_UTIL_H_

#include <cstddef>
#include <tuple>
#include <utility>
#include <vector>

#include <glog/logging.h>

#include "kudu/gutil/logging-inl.h"

//
// Find*()
//

// Returns a const reference to the value associated with the given key if it
// exists. Crashes otherwise.
//
// This is intended as a replacement for operator[] as an rvalue (for reading)
// when the key is guaranteed to exist.
//
// operator[] for lookup is discouraged for several reasons:
//  * It has a side-effect of inserting missing keys
//  * It is not thread-safe (even when it is not inserting, it can still
//      choose to resize the underlying storage)
//  * It invalidates iterators (when it chooses to resize)
//  * It default constructs a value object even if it doesn't need to
//
// This version assumes the key is printable, and includes it in the fatal log
// message.
template <class Collection>
const typename Collection::mapped_type&
FindOrDie(const Collection& collection,
          const typename Collection::key_type& key) {
  auto it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

// Same as above, but returns a non-const reference.
template <class Collection>
typename Collection::mapped_type&
FindOrDie(Collection& collection,  // NOLINT
          const typename Collection::key_type& key) {
  auto it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

// Same as FindOrDie above, but doesn't log the key on failure.
template <class Collection>
const typename Collection::mapped_type&
FindOrDieNoPrint(const Collection& collection,
                 const typename Collection::key_type& key) {
  typename Collection::const_iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found";
  return it->second;
}

// Same as above, but returns a non-const reference.
template <class Collection>
typename Collection::mapped_type&
FindOrDieNoPrint(Collection& collection,  // NOLINT
                 const typename Collection::key_type& key) {
  typename Collection::iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found";
  return it->second;
}

// Returns a const reference to the value associated with the given key if it
// exists, otherwise a const reference to the provided default value is
// returned.
//
// WARNING: If a temporary object is passed as the default "value," this
// function will return a reference to that temporary object, which will be
// destroyed by the end of the statement. Specifically, if you have a map with
// string values, and you pass a char* as the default "value," either use the
// returned value immediately or store it in a string (not string&). Details:
template <class Collection>
const typename Collection::mapped_type&
FindWithDefault(const Collection& collection,
                const typename Collection::key_type& key,
                const typename Collection::mapped_type& value) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return value;
  }
  return it->second;
}

// Returns a pointer to the const value associated with the given key if it
// exists, or NULL otherwise.
template <class Collection>
const typename Collection::mapped_type*
FindOrNull(const Collection& collection,
           const typename Collection::key_type& key) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return 0;
  }
  return &it->second;
}

// Same as above but returns a pointer to the non-const value.
template <class Collection>
typename Collection::mapped_type*
FindOrNull(Collection& collection,  // NOLINT
           const typename Collection::key_type& key) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return 0;
  }
  return &it->second;
}

// Returns a pointer to the const value associated with the greatest key
// that's less than or equal to the given key, or NULL if no such key exists.
template <class Collection>
const typename Collection::mapped_type*
FindFloorOrNull(const Collection& collection,
                const typename Collection::key_type& key) {
  auto it = collection.upper_bound(key);
  if (it == collection.begin()) {
    return 0;
  }
  return &(--it)->second;
}

// Same as above but returns a pointer to the non-const value.
template <class Collection>
typename Collection::mapped_type*
FindFloorOrNull(Collection& collection,  // NOLINT
                const typename Collection::key_type& key) {
  auto it = collection.upper_bound(key);
  if (it == collection.begin()) {
    return 0;
  }
  return &(--it)->second;
}

// Returns a const-reference to the value associated with the greatest key
// that's less than or equal to the given key, or crashes if it does not exist.
template <class Collection>
const typename Collection::mapped_type&
FindFloorOrDie(const Collection& collection,
               const typename Collection::key_type& key) {
  auto it = collection.upper_bound(key);
  CHECK(it != collection.begin());
  return (--it)->second;
}

// Same as above, but returns a non-const reference.
template <class Collection>
typename Collection::mapped_type&
FindFloorOrDie(Collection& collection,
               const typename Collection::key_type& key) {
  auto it = collection.upper_bound(key);
  CHECK(it != collection.begin());
  return (--it)->second;
}

// Returns the pointer value associated with the given key. If none is found,
// NULL is returned. The function is designed to be used with a map of keys to
// pointers.
//
// This function does not distinguish between a missing key and a key mapped
// to a NULL value.
template <class Collection>
typename Collection::mapped_type
FindPtrOrNull(const Collection& collection,
              const typename Collection::key_type& key) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return typename Collection::mapped_type(0);
  }
  return it->second;
}

// Same as above, except takes non-const reference to collection.
//
// This function is needed for containers that propagate constness to the
// pointee, such as boost::ptr_map.
template <class Collection>
typename Collection::mapped_type
FindPtrOrNull(Collection& collection,  // NOLINT
              const typename Collection::key_type& key) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return typename Collection::mapped_type(0);
  }
  return it->second;
}

// FindPtrOrNull like function for maps whose value is a smart pointer like shared_ptr or
// unique_ptr.
// Returns the raw pointer contained in the smart pointer for the first found key, if it exists,
// or null if it doesn't.
template <class Collection>
typename Collection::mapped_type::element_type*
FindPointeeOrNull(const Collection& collection,  // NOLINT,
                  const typename Collection::key_type& key) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return nullptr;
  }
  return it->second.get();
}

// Finds the value associated with the given key and copies it to *value (if not
// NULL). Returns false if the key was not found, true otherwise.
template <class Collection, class Key, class Value>
bool FindCopy(const Collection& collection,
              const Key& key,
              Value* const value) {
  auto it = collection.find(key);
  if (it == collection.end()) {
    return false;
  }
  if (value) {
    *value = it->second;
  }
  return true;
}

//
// Contains*()
//

// Returns true iff the given collection contains the given key.
template <class Collection, class Key>
bool ContainsKey(const Collection& collection, const Key& key) {
  return collection.find(key) != collection.end();
}

// Returns true iff the given collection contains the given key-value pair.
template <class Collection, class Key, class Value>
bool ContainsKeyValuePair(const Collection& collection,
                          const Key& key,
                          const Value& value) {
  typedef typename Collection::const_iterator const_iterator;
  std::pair<const_iterator, const_iterator> range = collection.equal_range(key);
  for (const_iterator it = range.first; it != range.second; ++it) {
    if (it->second == value) {
      return true;
    }
  }
  return false;
}

//
// Insert*()
//

// Inserts the given key-value pair into the collection. Returns true if the
// given key didn't previously exist. If the given key already existed in the
// map, its value is changed to the given "value" and false is returned.
template <class Collection>
bool InsertOrUpdate(Collection* const collection,
                    const typename Collection::value_type& vt) {
  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
  if (!ret.second) {
    // update
    ret.first->second = vt.second;
    return false;
  }
  return true;
}

// Same as above, except that the key and value are passed separately.
template <class Collection>
bool InsertOrUpdate(Collection* const collection,
                    const typename Collection::key_type& key,
                    const typename Collection::mapped_type& value) {
  return InsertOrUpdate(
      collection, typename Collection::value_type(key, value));
}

// Inserts/updates all the key-value pairs from the range defined by the
// iterators "first" and "last" into the given collection.
template <class Collection, class InputIterator>
void InsertOrUpdateMany(Collection* const collection,
                        InputIterator first, InputIterator last) {
  for (; first != last; ++first) {
    InsertOrUpdate(collection, *first);
  }
}

// Change the value associated with a particular key in a map or hash_map
// of the form map<Key, Value*> which owns the objects pointed to by the
// value pointers.  If there was an existing value for the key, it is deleted.
// True indicates an insert took place, false indicates an update + delete.
template <class Collection>
bool InsertAndDeleteExisting(
    Collection* const collection,
    const typename Collection::key_type& key,
    const typename Collection::mapped_type& value) {
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(typename Collection::value_type(key, value));
  if (!ret.second) {
    delete ret.first->second;
    ret.first->second = value;
    return false;
  }
  return true;
}

// Inserts the given key and value into the given collection iff the given key
// did NOT already exist in the collection. If the key previously existed in the
// collection, the value is not changed. Returns true if the key-value pair was
// inserted; returns false if the key was already present.
template <class Collection>
bool InsertIfNotPresent(Collection* const collection,
                        const typename Collection::value_type& vt) {
  return collection->insert(vt).second;
}

// Same as above except the key and value are passed separately.
template <class Collection>
bool InsertIfNotPresent(
    Collection* const collection,
    const typename Collection::key_type& key,
    const typename Collection::mapped_type& value) {
  return InsertIfNotPresent(
      collection, typename Collection::value_type(key, value));
}

// Same as above except dies if the key already exists in the collection.
template <class Collection>
void InsertOrDie(Collection* const collection,
                 const typename Collection::value_type& value) {
  CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value;
}

// Same as above except doesn't log the value on error.
template <class Collection>
void InsertOrDieNoPrint(Collection* const collection,
                        const typename Collection::value_type& value) {
  CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
}

// Inserts the key-value pair into the collection. Dies if key was already
// present.
template <class Collection>
void InsertOrDie(Collection* const collection,
                 const typename Collection::key_type& key,
                 const typename Collection::mapped_type& data) {
  CHECK(InsertIfNotPresent(collection, key, data))
      << "duplicate key: " << key;
}

// Same as above except deson't log the key on error.
template <class Collection>
void InsertOrDieNoPrint(
    Collection* const collection,
    const typename Collection::key_type& key,
    const typename Collection::mapped_type& data) {
  CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key.";
}

// Inserts a new key and default-initialized value. Dies if the key was already
// present. Returns a reference to the value. Example usage:
//
// map<int, SomeProto> m;
// SomeProto& proto = InsertKeyOrDie(&m, 3);
// proto.set_field("foo");
template <class Collection>
typename Collection::mapped_type& InsertKeyOrDie(
    Collection* const collection,
    const typename Collection::key_type& key) {
  typedef typename Collection::value_type value_type;
  std::pair<typename Collection::iterator, bool> res =
      collection->insert(value_type(key, typename Collection::mapped_type()));
  CHECK(res.second) << "duplicate key: " << key;
  return res.first->second;
}

//
// Emplace*()
//

// Dancing with std::enable_if() is necessary to make these two functions
// below work for both dictionary-like and set-like containers as well.
// The idea is that for dictionary-like containers Collection::value_type
// is always pair<const key_type, mapped_type>, so it cannot be the same
// as key type.
template <class Collection, class... Args>
typename std::enable_if<
    std::is_same<typename Collection::key_type,
                 typename Collection::value_type>::value,
    bool>::type
EmplaceIfNotPresent(Collection* const collection, Args&&... args) {
  return collection->emplace(std::forward<Args>(args)...).second;
}

template <class Collection, class... Args>
typename std::enable_if<
    !std::is_same<typename Collection::key_type,
                  typename Collection::value_type>::value,
    bool>::type
EmplaceIfNotPresent(Collection* const collection, Args&&... args) {
  return collection->try_emplace(std::forward<Args>(args)...).second;
}

// Emplaces the given key-value pair into the collection. Returns true if the
// given key didn't previously exist. If the given key already existed in the
// map, its value is changed to the given "value" and false is returned.
template <class Collection>
bool EmplaceOrUpdate(Collection* const collection,
                     const typename Collection::key_type& key,
                     typename Collection::mapped_type&& value) {
  return collection->insert_or_assign(
      key, std::forward<typename Collection::mapped_type>(value)).second;
}

// Given the key and parameters to construct the mapped object in-place,
// EmplaceOrDie() returns reference to the mapped object for dictionary-like
// containers or constant reference to the element itself for set-like ones.
// See the comment for EmplaceIfNotPresent() for details behind the template
// meta-programming details.
template <class Collection, class... Args>
typename std::enable_if<
    std::is_same<typename Collection::key_type,
                 typename Collection::value_type>::value,
    const typename Collection::value_type&>::type
EmplaceOrDie(Collection* const collection, Args&&... args) {
  auto res = collection->emplace(std::forward<Args>(args)...);
  CHECK(res.second) << "duplicate value";
  return *res.first;
}

template <class Collection, class... Args>
typename std::enable_if<
    !std::is_same<typename Collection::key_type,
                  typename Collection::value_type>::value,
    typename Collection::mapped_type&>::type
EmplaceOrDie(Collection* const collection, Args&&... args) {
  auto res = collection->emplace(std::forward<Args>(args)...);
  CHECK(res.second) << "duplicate value";
  return res.first->second;
}

//
// Lookup*()
//

// Looks up a given key and value pair in a collection and inserts the key-value
// pair if it's not already present. Returns a reference to the value associated
// with the key.
template <class Collection>
typename Collection::mapped_type&
LookupOrInsert(Collection* const collection,
               const typename Collection::value_type& vt) {
  return collection->insert(vt).first->second;
}

// Same as above except the key-value are passed separately.
template <class Collection>
typename Collection::mapped_type&
LookupOrInsert(Collection* const collection,
               const typename Collection::key_type& key,
               const typename Collection::mapped_type& value) {
  return LookupOrInsert(
      collection, typename Collection::value_type(key, value));
}

// It's similar to LookupOrInsert() but uses the emplace and r-value mechanics
// to achieve the desired results, constructing the element in-place in the
// container. The constructor of the new element is called with exactly the same
// arguments as supplied to emplace, forwarded via std::forward<Args>(args).
// The element is constructed only if there was no element with the specified
// key in the container.
// For details, see
//   https://en.cppreference.com/w/cpp/container/map/try_emplace
//   https://en.cppreference.com/w/cpp/container/unordered_map/try_emplace
template <class Collection, class... Args>
typename Collection::mapped_type&
LookupOrEmplace(Collection* const collection, Args&&... args) {
  return collection->try_emplace(std::forward<Args>(args)...).first->second;
}

// Counts the number of equivalent elements in the given "sequence", and stores
// the results in "count_map" with element as the key and count as the value.
//
// Example:
//   vector<string> v = {"a", "b", "c", "a", "b"};
//   map<string, int> m;
//   AddTokenCounts(v, 1, &m);
//   assert(m["a"] == 2);
//   assert(m["b"] == 2);
//   assert(m["c"] == 1);
template <typename Sequence, typename Collection>
void AddTokenCounts(
    const Sequence& sequence,
    const typename Collection::mapped_type& increment,
    Collection* const count_map) {
  for (typename Sequence::const_iterator it = sequence.begin();
       it != sequence.end(); ++it) {
    typename Collection::mapped_type& value =
        LookupOrInsert(count_map, *it,
                       typename Collection::mapped_type());
    value += increment;
  }
}

// Helpers for LookupOrInsertNew(), needed to create a new value type when the
// type itself is a pointer, i.e., these extract the actual type from a pointer.
template <class T>
void MapUtilAssignNewDefaultInstance(T** location) {
  *location = new T();
}

template <class T, class Arg>
void MapUtilAssignNewInstance(T** location, const Arg &arg) {
  *location = new T(arg);
}

// Returns a reference to the value associated with key. If not found, a value
// is default constructed on the heap and added to the map.
//
// This function is useful for containers of the form map<Key, Value*>, where
// inserting a new key, value pair involves constructing a new heap-allocated
// Value, and storing a pointer to that in the collection.
template <class Collection>
typename Collection::mapped_type&
LookupOrInsertNew(Collection* const collection,
                  const typename Collection::key_type& key) {
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(
          typename Collection::value_type(key,
              static_cast<typename Collection::mapped_type>(NULL)));
  if (ret.second) {
    // This helper is needed to 'extract' the Value type from the type of the
    // container value, which is (Value*).
    MapUtilAssignNewDefaultInstance(&(ret.first->second));
  }
  return ret.first->second;
}

// Same as above but constructs the value using the single-argument constructor
// and the given "arg".
template <class Collection, class Arg>
typename Collection::mapped_type&
LookupOrInsertNew(Collection* const collection,
                  const typename Collection::key_type& key,
                  const Arg& arg) {
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(
          typename Collection::value_type(
              key,
              static_cast<typename Collection::mapped_type>(NULL)));
  if (ret.second) {
    // This helper is needed to 'extract' the Value type from the type of the
    // container value, which is (Value*).
    MapUtilAssignNewInstance(&(ret.first->second), arg);
  }
  return ret.first->second;
}

// Lookup of linked/shared pointers is used in two scenarios:
//
// Use LookupOrInsertSharedPtr if the container does not own the elements
// for their whole lifetime. This is typically the case when a reader allows
// parallel updates to the container. In this case a Mutex only needs to lock
// container operations, but all element operations must be performed on the
// shared pointer. Finding an element must be performed using FindPtr*() and
// cannot be done with FindLinkedPtr*() even though it compiles.

// Lookup a key in a map or hash_map whose values are shared_ptrs.  If it is
// missing, set collection[key].reset(new Value::element_type). Unlike
// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of
// the raw pointer. Value::element_type must be default constructable.
template <class Collection>
typename Collection::mapped_type&
LookupOrInsertNewSharedPtr(
    Collection* const collection,
    const typename Collection::key_type& key) {
  typedef typename Collection::mapped_type SharedPtr;
  typedef typename Collection::mapped_type::element_type Element;
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(typename Collection::value_type(key, SharedPtr()));
  if (ret.second) {
    ret.first->second.reset(new Element());
  }
  return ret.first->second;
}

// A variant of LookupOrInsertNewSharedPtr where the value is constructed using
// constructor arguments.  Note: the constructor arguments are computed even if
// they will not be used, so only values cheap to compute should be passed
// here.  On the other hand it does not matter how expensive the construction
// of the actual stored value is, as that only occurs if necessary.
template <class Collection, class... Args>
typename Collection::mapped_type&
LookupOrInsertNewSharedPtr(
    Collection* const collection,
    const typename Collection::key_type& key,
    const Args&... args) {
  typedef typename Collection::mapped_type SharedPtr;
  typedef typename Collection::mapped_type::element_type Element;
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(typename Collection::value_type(key, SharedPtr()));
  if (ret.second) {
    ret.first->second.reset(new Element(args...));
  }
  return ret.first->second;
}

//
// Misc Utility Functions
//

// Updates the value associated with the given key. If the key was not already
// present, then the key-value pair are inserted and "previous" is unchanged. If
// the key was already present, the value is updated and "*previous" will
// contain a copy of the old value.
//
// InsertOrReturnExisting has complementary behavior that returns the
// address of an already existing value, rather than updating it.
template <class Collection>
bool UpdateReturnCopy(Collection* const collection,
                      const typename Collection::key_type& key,
                      const typename Collection::mapped_type& value,
                      typename Collection::mapped_type* previous) {
  std::pair<typename Collection::iterator, bool> ret =
      collection->insert(typename Collection::value_type(key, value));
  if (!ret.second) {
    // update
    if (previous) {
      *previous = ret.first->second;
    }
    ret.first->second = value;
    return true;
  }
  return false;
}

// Same as above except that the key and value are passed as a pair.
template <class Collection>
bool UpdateReturnCopy(Collection* const collection,
                      const typename Collection::value_type& vt,
                      typename Collection::mapped_type* previous) {
  std::pair<typename Collection::iterator, bool> ret =
    collection->insert(vt);
  if (!ret.second) {
    // update
    if (previous) {
      *previous = ret.first->second;
    }
    ret.first->second = vt.second;
    return true;
  }
  return false;
}

// Tries to insert the given key-value pair into the collection. Returns NULL if
// the insert succeeds. Otherwise, returns a pointer to the existing value.
//
// This complements UpdateReturnCopy in that it allows to update only after
// verifying the old value and still insert quickly without having to look up
// twice. Unlike UpdateReturnCopy this also does not come with the issue of an
// undefined previous* in case new data was inserted.
template <class Collection>
typename Collection::mapped_type* const
InsertOrReturnExisting(Collection* const collection,
                       const typename Collection::value_type& vt) {
  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
  if (ret.second) {
    return NULL;  // Inserted, no existing previous value.
  } else {
    return &ret.first->second;  // Return address of already existing value.
  }
}

// Same as above, except for explicit key and data.
template <class Collection>
typename Collection::mapped_type* const
InsertOrReturnExisting(
    Collection* const collection,
    const typename Collection::key_type& key,
    const typename Collection::mapped_type& data) {
  return InsertOrReturnExisting(collection,
                                typename Collection::value_type(key, data));
}

// Saves the reverse mapping into reverse. Key/value pairs are inserted in the
// order the iterator returns them.
template <class Collection, class ReverseCollection>
void ReverseMap(const Collection& collection,
                ReverseCollection* const reverse) {
  CHECK(reverse != NULL);
  for (typename Collection::const_iterator it = collection.begin();
       it != collection.end();
       ++it) {
    InsertOrUpdate(reverse, it->second, it->first);
  }
}

// Erases the collection item identified by the given key, and returns the value
// associated with that key. It is assumed that the value (i.e., the
// mapped_type) is a pointer. Returns NULL if the key was not found in the
// collection.
//
// Examples:
//   map<string, MyType*> my_map;
//
// One line cleanup:
//     delete EraseKeyReturnValuePtr(&my_map, "abc");
//
// Use returned value:
//     unique_ptr<MyType> value_ptr(EraseKeyReturnValuePtr(&my_map, "abc"));
//     if (value_ptr.get())
//       value_ptr->DoSomething();
//
// Note: if 'collection' is a multimap, this will only erase and return the
// first value.
template <class Collection>
typename Collection::mapped_type EraseKeyReturnValuePtr(
    Collection* const collection,
    const typename Collection::key_type& key) {
  auto it = collection->find(key);
  if (it == collection->end()) {
    return typename Collection::mapped_type();
  }
  typename Collection::mapped_type v = std::move(it->second);
  collection->erase(it);
  return v;
}

// Inserts all the keys from map_container into key_container, which must
// support insert(MapContainer::key_type).
//
// Note: any initial contents of the key_container are not cleared.
template <class MapContainer, class KeyContainer>
void InsertKeysFromMap(const MapContainer& map_container,
                       KeyContainer* key_container) {
  CHECK(key_container != NULL);
  for (typename MapContainer::const_iterator it = map_container.begin();
       it != map_container.end(); ++it) {
    key_container->insert(it->first);
  }
}

// Appends all the keys from map_container into key_container, which must
// support push_back(MapContainer::key_type).
//
// Note: any initial contents of the key_container are not cleared.
template <class MapContainer, class KeyContainer>
void AppendKeysFromMap(const MapContainer& map_container,
                       KeyContainer* key_container) {
  CHECK(key_container != NULL);
  for (typename MapContainer::const_iterator it = map_container.begin();
       it != map_container.end(); ++it) {
    key_container->push_back(it->first);
  }
}

// A more specialized overload of AppendKeysFromMap to optimize reallocations
// for the common case in which we're appending keys to a vector and hence can
// (and sometimes should) call reserve() first.
//
// (It would be possible to play SFINAE games to call reserve() for any
// container that supports it, but this seems to get us 99% of what we need
// without the complexity of a SFINAE-based solution.)
template <class MapContainer, class KeyType>
void AppendKeysFromMap(const MapContainer& map_container,
                       std::vector<KeyType>* key_container) {
  CHECK(key_container != NULL);
  // We now have the opportunity to call reserve(). Calling reserve() every
  // time is a bad idea for some use cases: libstdc++'s implementation of
  // vector<>::reserve() resizes the vector's backing store to exactly the
  // given size (unless it's already at least that big). Because of this,
  // the use case that involves appending a lot of small maps (total size
  // N) one by one to a vector would be O(N^2). But never calling reserve()
  // loses the opportunity to improve the use case of adding from a large
  // map to an empty vector (this improves performance by up to 33%). A
  // number of heuristics are possible; see the discussion in
  // cl/34081696. Here we use the simplest one.
  if (key_container->empty()) {
    key_container->reserve(map_container.size());
  }
  for (typename MapContainer::const_iterator it = map_container.begin();
       it != map_container.end(); ++it) {
    key_container->push_back(it->first);
  }
}

// Inserts all the values from map_container into value_container, which must
// support push_back(MapContainer::mapped_type).
//
// Note: any initial contents of the value_container are not cleared.
template <class MapContainer, class ValueContainer>
void AppendValuesFromMap(const MapContainer& map_container,
                         ValueContainer* value_container) {
  CHECK(value_container != NULL);
  for (typename MapContainer::const_iterator it = map_container.begin();
       it != map_container.end(); ++it) {
    value_container->push_back(it->second);
  }
}

template <class MapContainer, class ValueContainer>
void EmplaceValuesFromMap(MapContainer&& map_container,
                          ValueContainer* value_container) {
  CHECK(value_container != nullptr);
  // See AppendKeysFromMap for why this is done.
  if (value_container->empty()) {
    value_container->reserve(map_container.size());
  }
  for (auto&& entry : map_container) {
    value_container->emplace_back(std::move(entry.second));
  }
}

// A more specialized overload of AppendValuesFromMap to optimize reallocations
// for the common case in which we're appending values to a vector and hence
// can (and sometimes should) call reserve() first.
//
// (It would be possible to play SFINAE games to call reserve() for any
// container that supports it, but this seems to get us 99% of what we need
// without the complexity of a SFINAE-based solution.)
template <class MapContainer, class ValueType>
void AppendValuesFromMap(const MapContainer& map_container,
                         std::vector<ValueType>* value_container) {
  EmplaceValuesFromMap(map_container, value_container);
}

// Compute and insert new value if it's absent from the map. Return a pair with a reference to the
// value and a bool indicating whether it was absent at first.
//
// This inspired on a similar java construct (url split in two lines):
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html
// #computeIfAbsent-K-java.util.function.Function
//
// It takes a reference to the key and a lambda function. If the key exists in the map, returns
// a pair with a pointer to the current value and 'false'. If the key does not exist in the map,
// it uses the lambda function to create a value, inserts it into the map, and returns a pair with
// a pointer to the new value and 'true'.
//
// Example usage:
//
// auto result = ComputeIfAbsentReturnAbsense(&my_collection,
//                                            my_key,
//                                            [] { return new_value; });
// MyValue* const value = result.first;
// if (result.second) ....
//
// The ComputePair* variants expect a lambda that creates a pair<k, v>. This
// can be useful if the key is a StringPiece pointing to external state to
// avoid excess memory for the keys, while being safer in multi-threaded
// contexts, e.g. in case the key goes out of scope before the container does.
//
// Example usage:
//
// map<StringPiece, int, GoodFastHash<StringPiece>> string_to_idx;
// vector<unique_ptr<StringPB>> pbs;
// auto result = ComputePairIfAbsentReturnAbsense(&string_to_idx, my_key,
//     [&]() {
//       unique_ptr<StringPB> s = new StringPB();
//       s->set_string(my_key);
//       int idx = pbs.size();
//       pbs.emplace_back(s.release());
//       return make_pair(StringPiece(pbs.back()->string()), idx);
//     });
template <class MapContainer, typename Function>
std::pair<typename MapContainer::mapped_type* const, bool>
ComputePairIfAbsentReturnAbsense(MapContainer* container,
                                 const typename MapContainer::key_type& key,
                                 Function compute_pair_func) {
  typename MapContainer::iterator iter = container->find(key);
  bool new_value = iter == container->end();
  if (new_value) {
    auto p = compute_pair_func();
    std::pair<typename MapContainer::iterator, bool> result =
        container->emplace(std::move(p.first), std::move(p.second));
    DCHECK(result.second) << "duplicate key: " << key;
    iter = result.first;
  }
  return std::make_pair(&iter->second, new_value);
}
template <class MapContainer, typename Function>
std::pair<typename MapContainer::mapped_type* const, bool>
ComputeIfAbsentReturnAbsense(MapContainer* container,
                             const typename MapContainer::key_type& key,
                             Function compute_func) {
  return ComputePairIfAbsentReturnAbsense(container, key, [&key, &compute_func] {
    return std::make_pair(key, compute_func());
  });
};

// Like the above but doesn't return a pair, just returns a pointer to the value.
// Example usage:
//
// MyValue* const value = ComputeIfAbsent(&my_collection,
//                                        my_key,
//                                        [] { return new_value; });
//
template <class MapContainer, typename Function>
typename MapContainer::mapped_type* const
ComputeIfAbsent(MapContainer* container,
                const typename MapContainer::key_type& key,
                Function compute_func) {
  return ComputeIfAbsentReturnAbsense(container, key, compute_func).first;
};

template <class MapContainer, typename Function>
typename MapContainer::mapped_type* const
ComputePairIfAbsent(MapContainer* container,
                    const typename MapContainer::key_type& key,
                    Function compute_pair_func) {
  return ComputePairIfAbsentReturnAbsense<MapContainer, Function>(container, key, compute_pair_func).first;
};

#endif  // UTIL_GTL_MAP_UTIL_H_
