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
17 
18 #ifndef TENSORFLOW_LIB_GTL_STL_UTIL_H_
19 #define TENSORFLOW_LIB_GTL_STL_UTIL_H_
20 
21 #include <stddef.h>
22 #include <algorithm>
23 #include <iterator>
24 #include <memory>
25 #include <string>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
30 #include "absl/meta/type_traits.h"
31 
32 namespace tensorflow {
33 namespace gtl {
34 
35 // Returns a char* pointing to the beginning of a string's internal buffer.
36 // The result is a valid "null-terminated byte string", even if *str is empty.
37 // Up to C++14 it is not valid to *write* to the null terminator; as of C++17,
38 // it is valid to write zero to the null terminator (but not any other value).
string_as_array(string * str)39 inline char* string_as_array(string* str) { return &*str->begin(); }
40 
41 // The following vector_as_array functions return raw pointers to the underlying
42 // data buffer. The return value is unspecified (but valid) if the input range
43 // is empty.
44 template <typename T, typename Allocator>
vector_as_array(std::vector<T,Allocator> * v)45 inline T* vector_as_array(std::vector<T, Allocator>* v) {
46   return v->data();
47 }
48 
49 template <typename T, typename Allocator>
vector_as_array(const std::vector<T,Allocator> * v)50 inline const T* vector_as_array(const std::vector<T, Allocator>* v) {
51   return v->data();
52 }
53 
54 namespace gtl_internal {
55 
56 // HasMember is true_type or false_type, depending on whether or not
57 // T has a __resize_default_init member. Resize will call the
58 // __resize_default_init member if it exists, and will call the resize
59 // member otherwise.
60 template <typename string_type, typename = void>
61 struct ResizeUninitializedTraits {
62   using HasMember = std::false_type;
ResizeResizeUninitializedTraits63   static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
64 };
65 
66 // __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
67 // ::string implementation.
68 template <typename string_type>
69 struct ResizeUninitializedTraits<
70     string_type, absl::void_t<decltype(std::declval<string_type&>()
71                                            .__resize_default_init(237))> > {
72   using HasMember = std::true_type;
73   static void Resize(string_type* s, size_t new_size) {
74     s->__resize_default_init(new_size);
75   }
76 };
77 
78 }  // namespace gtl_internal
79 
80 // Like str->resize(new_size), except any new characters added to "*str" as a
81 // result of resizing may be left uninitialized, rather than being filled with
82 // '0' bytes. Typically used when code is then going to overwrite the backing
83 // store of the string with known data.
84 inline void STLStringResizeUninitialized(string* s, size_t new_size) {
85   gtl_internal::ResizeUninitializedTraits<string>::Resize(s, new_size);
86 }
87 
88 // Calls delete (non-array version) on the SECOND item (pointer) in each pair in
89 // the range [begin, end).
90 //
91 // Note: If you're calling this on an entire container, you probably want to
92 // call STLDeleteValues(&container) instead, or use ValueDeleter.
93 template <typename ForwardIterator>
94 void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
95                                           ForwardIterator end) {
96   while (begin != end) {
97     ForwardIterator temp = begin;
98     ++begin;
99     delete temp->second;
100   }
101 }
102 
103 // Deletes all the elements in an STL container and clears the container. This
104 // function is suitable for use with a vector, set, hash_set, or any other STL
105 // container which defines sensible begin(), end(), and clear() methods.
106 //
107 // If container is NULL, this function is a no-op.
108 template <typename T>
109 void STLDeleteElements(T* container) {
110   if (!container) return;
111   auto it = container->begin();
112   while (it != container->end()) {
113     auto temp = it;
114     ++it;
115     delete *temp;
116   }
117   container->clear();
118 }
119 
120 // Given an STL container consisting of (key, value) pairs, STLDeleteValues
121 // deletes all the "value" components and clears the container. Does nothing in
122 // the case it's given a NULL pointer.
123 template <typename T>
124 void STLDeleteValues(T* container) {
125   if (!container) return;
126   auto it = container->begin();
127   while (it != container->end()) {
128     auto temp = it;
129     ++it;
130     delete temp->second;
131   }
132   container->clear();
133 }
134 
135 // Sorts and removes duplicates from a sequence container.
136 template <typename T>
137 inline void STLSortAndRemoveDuplicates(T* v) {
138   std::sort(v->begin(), v->end());
139   v->erase(std::unique(v->begin(), v->end()), v->end());
140 }
141 
142 }  // namespace gtl
143 }  // namespace tensorflow
144 
145 #endif  // TENSORFLOW_LIB_GTL_STL_UTIL_H_
146