Home | History | Annotate | Download | only in gtl
      1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 // This file provides utility functions for use with STL map-like data
     17 // structures, such as std::map and hash_map. Some functions will also work with
     18 // sets, such as ContainsKey().
     19 
     20 #ifndef TENSORFLOW_LIB_GTL_MAP_UTIL_H_
     21 #define TENSORFLOW_LIB_GTL_MAP_UTIL_H_
     22 
     23 #include <stddef.h>
     24 #include <iterator>
     25 #include <memory>
     26 #include <string>
     27 #include <utility>
     28 
     29 namespace tensorflow {
     30 namespace gtl {
     31 
     32 // Returns a pointer to the const value associated with the given key if it
     33 // exists, or NULL otherwise.
     34 template <class Collection>
     35 const typename Collection::value_type::second_type* FindOrNull(
     36     const Collection& collection,
     37     const typename Collection::value_type::first_type& key) {
     38   typename Collection::const_iterator it = collection.find(key);
     39   if (it == collection.end()) {
     40     return 0;
     41   }
     42   return &it->second;
     43 }
     44 
     45 // Same as above but returns a pointer to the non-const value.
     46 template <class Collection>
     47 typename Collection::value_type::second_type* FindOrNull(
     48     Collection& collection,  // NOLINT
     49     const typename Collection::value_type::first_type& key) {
     50   typename Collection::iterator it = collection.find(key);
     51   if (it == collection.end()) {
     52     return 0;
     53   }
     54   return &it->second;
     55 }
     56 
     57 // Returns the pointer value associated with the given key. If none is found,
     58 // NULL is returned. The function is designed to be used with a map of keys to
     59 // pointers.
     60 //
     61 // This function does not distinguish between a missing key and a key mapped
     62 // to a NULL value.
     63 template <class Collection>
     64 typename Collection::value_type::second_type FindPtrOrNull(
     65     const Collection& collection,
     66     const typename Collection::value_type::first_type& key) {
     67   typename Collection::const_iterator it = collection.find(key);
     68   if (it == collection.end()) {
     69     return typename Collection::value_type::second_type();
     70   }
     71   return it->second;
     72 }
     73 
     74 // Returns a const reference to the value associated with the given key if it
     75 // exists, otherwise returns a const reference to the provided default value.
     76 //
     77 // WARNING: If a temporary object is passed as the default "value,"
     78 // this function will return a reference to that temporary object,
     79 // which will be destroyed at the end of the statement. A common
     80 // example: if you have a map with string values, and you pass a char*
     81 // as the default "value," either use the returned value immediately
     82 // or store it in a string (not string&).
     83 template <class Collection>
     84 const typename Collection::value_type::second_type& FindWithDefault(
     85     const Collection& collection,
     86     const typename Collection::value_type::first_type& key,
     87     const typename Collection::value_type::second_type& value) {
     88   typename Collection::const_iterator it = collection.find(key);
     89   if (it == collection.end()) {
     90     return value;
     91   }
     92   return it->second;
     93 }
     94 
     95 // Inserts the given key-value pair into the collection. Returns true if and
     96 // only if the key from the given pair didn't previously exist. Otherwise, the
     97 // value in the map is replaced with the value from the given pair.
     98 template <class Collection>
     99 bool InsertOrUpdate(Collection* const collection,
    100                     const typename Collection::value_type& vt) {
    101   std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
    102   if (!ret.second) {
    103     // update
    104     ret.first->second = vt.second;
    105     return false;
    106   }
    107   return true;
    108 }
    109 
    110 // Same as above, except that the key and value are passed separately.
    111 template <class Collection>
    112 bool InsertOrUpdate(Collection* const collection,
    113                     const typename Collection::value_type::first_type& key,
    114                     const typename Collection::value_type::second_type& value) {
    115   return InsertOrUpdate(collection,
    116                         typename Collection::value_type(key, value));
    117 }
    118 
    119 // Inserts the given key and value into the given collection if and only if the
    120 // given key did NOT already exist in the collection. If the key previously
    121 // existed in the collection, the value is not changed. Returns true if the
    122 // key-value pair was inserted; returns false if the key was already present.
    123 template <class Collection>
    124 bool InsertIfNotPresent(Collection* const collection,
    125                         const typename Collection::value_type& vt) {
    126   return collection->insert(vt).second;
    127 }
    128 
    129 // Same as above except the key and value are passed separately.
    130 template <class Collection>
    131 bool InsertIfNotPresent(
    132     Collection* const collection,
    133     const typename Collection::value_type::first_type& key,
    134     const typename Collection::value_type::second_type& value) {
    135   return InsertIfNotPresent(collection,
    136                             typename Collection::value_type(key, value));
    137 }
    138 
    139 // Looks up a given key and value pair in a collection and inserts the key-value
    140 // pair if it's not already present. Returns a reference to the value associated
    141 // with the key.
    142 template <class Collection>
    143 typename Collection::value_type::second_type& LookupOrInsert(
    144     Collection* const collection, const typename Collection::value_type& vt) {
    145   return collection->insert(vt).first->second;
    146 }
    147 
    148 // Same as above except the key-value are passed separately.
    149 template <class Collection>
    150 typename Collection::value_type::second_type& LookupOrInsert(
    151     Collection* const collection,
    152     const typename Collection::value_type::first_type& key,
    153     const typename Collection::value_type::second_type& value) {
    154   return LookupOrInsert(collection,
    155                         typename Collection::value_type(key, value));
    156 }
    157 
    158 }  // namespace gtl
    159 }  // namespace tensorflow
    160 
    161 #endif  // TENSORFLOW_LIB_GTL_MAP_UTIL_H_
    162