Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / gprpp / map.h
diff --git a/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/gprpp/map.h b/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/gprpp/map.h
new file mode 100644 (file)
index 0000000..6a41a97
--- /dev/null
@@ -0,0 +1,564 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_MAP_H
+#define GRPC_CORE_LIB_GPRPP_MAP_H
+
+#include <grpc/support/port_platform.h>
+
+#include <string.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#if GRPC_USE_CPP_STD_LIB
+#include <map>
+#endif
+
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/pair.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/string_view.h"
+
+namespace grpc_core {
+
+struct StringLess {
+  bool operator()(const char* a, const char* b) const {
+    return strcmp(a, b) < 0;
+  }
+  bool operator()(const UniquePtr<char>& a, const UniquePtr<char>& b) const {
+    return strcmp(a.get(), b.get()) < 0;
+  }
+  bool operator()(const StringView& a, const StringView& b) const {
+    const size_t min_size = std::min(a.size(), b.size());
+    int c = strncmp(a.data(), b.data(), min_size);
+    if (c != 0) return c < 0;
+    return a.size() < b.size();
+  }
+};
+
+template <typename T>
+struct RefCountedPtrLess {
+  bool operator()(const RefCountedPtr<T>& p1,
+                  const RefCountedPtr<T>& p2) const {
+    return p1.get() < p2.get();
+  }
+};
+
+#if GRPC_USE_CPP_STD_LIB
+
+template <class Key, class T, class Compare = std::less<Key>>
+using Map = std::map<Key, T, Compare>;
+
+#else  // GRPC_USE_CPP_STD_LIB
+
+namespace testing {
+class MapTest;
+}
+
+// Alternative map implementation for grpc_core
+template <class Key, class T, class Compare = std::less<Key>>
+class Map {
+ public:
+  typedef Key key_type;
+  typedef T mapped_type;
+  typedef Pair<key_type, mapped_type> value_type;
+  typedef Compare key_compare;
+  class iterator;
+  class const_iterator;
+
+  Map() = default;
+  ~Map() { clear(); }
+
+  // Movable.
+  Map(Map&& other) : root_(other.root_), size_(other.size_) {
+    other.root_ = nullptr;
+    other.size_ = 0;
+  }
+  Map& operator=(Map&& other) {
+    if (this != &other) {
+      clear();
+      root_ = other.root_;
+      size_ = other.size_;
+      other.root_ = nullptr;
+      other.size_ = 0;
+    }
+    return *this;
+  }
+
+  // Copyable.
+  Map(const Map& other) {
+    for (const auto& p : other) {
+      emplace(p);
+    }
+  }
+  Map& operator=(const Map& other) {
+    if (this != &other) {
+      clear();
+      for (const auto& p : other) {
+        emplace(p);
+      }
+    }
+    return *this;
+  }
+
+  T& operator[](key_type&& key);
+  T& operator[](const key_type& key);
+  iterator find(const key_type& k);
+  size_t erase(const key_type& key);
+  // Removes the current entry and points to the next one
+  iterator erase(iterator iter);
+
+  size_t size() const { return size_; }
+
+  template <class... Args>
+  Pair<iterator, bool> emplace(Args&&... args);
+
+  Pair<iterator, bool> insert(value_type&& pair) {
+    return emplace(std::move(pair));
+  }
+
+  Pair<iterator, bool> insert(const value_type& pair) { return emplace(pair); }
+
+  bool empty() const { return root_ == nullptr; }
+
+  void clear() {
+    auto iter = begin();
+    while (!empty()) {
+      iter = erase(iter);
+    }
+  }
+
+  iterator begin() {
+    Entry* curr = GetMinEntry(root_);
+    return iterator(this, curr);
+  }
+
+  iterator end() { return iterator(this, nullptr); }
+
+  const_iterator begin() const {
+    Entry* curr = GetMinEntry(root_);
+    return const_iterator(this, curr);
+  }
+
+  const_iterator end() const { return const_iterator(this, nullptr); }
+
+  iterator lower_bound(const Key& k) {
+    // This is a workaround for "const key_compare compare;"
+    // because some versions of compilers cannot build this by requiring
+    // a user-provided constructor. (ref: https://stackoverflow.com/q/7411515)
+    key_compare compare_tmp;
+    const key_compare& compare = compare_tmp;
+    return std::find_if(begin(), end(), [&k, &compare](const value_type& v) {
+      return !compare(v.first, k);
+    });
+  }
+
+ private:
+  friend class testing::MapTest;
+  struct Entry {
+    explicit Entry(value_type&& pair) : pair(std::move(pair)) {}
+    value_type pair;
+    Entry* left = nullptr;
+    Entry* right = nullptr;
+    int32_t height = 1;
+  };
+
+  static int32_t EntryHeight(const Entry* e) {
+    return e == nullptr ? 0 : e->height;
+  }
+
+  static Entry* GetMinEntry(Entry* e);
+  Entry* InOrderSuccessor(const Entry* e) const;
+  static Entry* RotateLeft(Entry* e);
+  static Entry* RotateRight(Entry* e);
+  static Entry* RebalanceTreeAfterInsertion(Entry* root, const key_type& k);
+  static Entry* RebalanceTreeAfterDeletion(Entry* root);
+  // Returns a pair with the first value being an iterator pointing to the
+  // inserted entry and the second value being the new root of the subtree
+  // after a rebalance
+  Pair<iterator, Entry*> InsertRecursive(Entry* root, value_type&& p);
+  // Returns a pair with the first value being an iterator pointing to the
+  // successor of the deleted entry and the second value being the new root of
+  // the subtree after a rebalance
+  Pair<iterator, Entry*> RemoveRecursive(Entry* root, const key_type& k);
+  // Return 0 if lhs = rhs
+  //        1 if lhs > rhs
+  //       -1 if lhs < rhs
+  static int CompareKeys(const Key& lhs, const Key& rhs);
+
+  Entry* root_ = nullptr;
+  size_t size_ = 0;
+};
+
+template <class Key, class T, class Compare>
+class Map<Key, T, Compare>::iterator
+    : public std::iterator<std::input_iterator_tag, Pair<Key, T>, int32_t,
+                           Pair<Key, T>*, Pair<Key, T>&> {
+ public:
+  iterator(const iterator& iter) : curr_(iter.curr_), map_(iter.map_) {}
+  bool operator==(const iterator& rhs) const { return (curr_ == rhs.curr_); }
+  bool operator!=(const iterator& rhs) const { return (curr_ != rhs.curr_); }
+
+  iterator& operator++() {
+    curr_ = map_->InOrderSuccessor(curr_);
+    return *this;
+  }
+
+  iterator operator++(int) {
+    Entry* prev = curr_;
+    curr_ = map_->InOrderSuccessor(curr_);
+    return iterator(map_, prev);
+  }
+
+  iterator& operator=(const iterator& other) {
+    if (this != &other) {
+      this->curr_ = other.curr_;
+      this->map_ = other.map_;
+    }
+    return *this;
+  }
+
+  // operator*()
+  value_type& operator*() { return curr_->pair; }
+  const value_type& operator*() const { return curr_->pair; }
+
+  // operator->()
+  value_type* operator->() { return &curr_->pair; }
+  value_type const* operator->() const { return &curr_->pair; }
+
+ private:
+  friend class Map<key_type, mapped_type, key_compare>;
+  using GrpcMap = typename ::grpc_core::Map<Key, T, Compare>;
+  iterator(GrpcMap* map, Entry* curr) : curr_(curr), map_(map) {}
+  Entry* curr_;
+  GrpcMap* map_;
+};
+
+template <class Key, class T, class Compare>
+class Map<Key, T, Compare>::const_iterator
+    : public std::iterator<std::input_iterator_tag, Pair<Key, T>, int32_t,
+                           Pair<Key, T>*, Pair<Key, T>&> {
+ public:
+  const_iterator(const const_iterator& iter)
+      : curr_(iter.curr_), map_(iter.map_) {}
+  bool operator==(const const_iterator& rhs) const {
+    return (curr_ == rhs.curr_);
+  }
+  bool operator!=(const const_iterator& rhs) const {
+    return (curr_ != rhs.curr_);
+  }
+
+  const_iterator& operator++() {
+    curr_ = map_->InOrderSuccessor(curr_);
+    return *this;
+  }
+
+  const_iterator operator++(int) {
+    Entry* prev = curr_;
+    curr_ = map_->InOrderSuccessor(curr_);
+    return const_iterator(map_, prev);
+  }
+
+  const_iterator& operator=(const const_iterator& other) {
+    if (this != &other) {
+      this->curr_ = other.curr_;
+      this->map_ = other.map_;
+    }
+    return *this;
+  }
+
+  // operator*()
+  const value_type& operator*() const { return curr_->pair; }
+
+  // operator->()
+  const value_type* operator->() const { return &curr_->pair; }
+
+ private:
+  friend class Map<key_type, mapped_type, key_compare>;
+  using GrpcMap = typename ::grpc_core::Map<Key, T, Compare>;
+  const_iterator(const GrpcMap* map, Entry* curr) : curr_(curr), map_(map) {}
+  Entry* curr_;
+  const GrpcMap* map_;
+};
+
+template <class Key, class T, class Compare>
+T& Map<Key, T, Compare>::operator[](key_type&& key) {
+  auto iter = find(key);
+  if (iter == end()) {
+    return emplace(std::move(key), T()).first->second;
+  }
+  return iter->second;
+}
+
+template <class Key, class T, class Compare>
+T& Map<Key, T, Compare>::operator[](const key_type& key) {
+  auto iter = find(key);
+  if (iter == end()) {
+    return emplace(key, T()).first->second;
+  }
+  return iter->second;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::iterator Map<Key, T, Compare>::find(
+    const key_type& k) {
+  Entry* iter = root_;
+  while (iter != nullptr) {
+    int comp = CompareKeys(iter->pair.first, k);
+    if (comp == 0) {
+      return iterator(this, iter);
+    } else if (comp < 0) {
+      iter = iter->right;
+    } else {
+      iter = iter->left;
+    }
+  }
+  return end();
+}
+
+template <class Key, class T, class Compare>
+template <class... Args>
+typename ::grpc_core::Pair<typename Map<Key, T, Compare>::iterator, bool>
+Map<Key, T, Compare>::emplace(Args&&... args) {
+  Pair<key_type, mapped_type> pair(std::forward<Args>(args)...);
+  iterator ret = find(pair.first);
+  bool insertion = false;
+  if (ret == end()) {
+    Pair<iterator, Entry*> p = InsertRecursive(root_, std::move(pair));
+    root_ = p.second;
+    ret = p.first;
+    insertion = true;
+    size_++;
+  }
+  return MakePair(ret, insertion);
+}
+
+template <class Key, class T, class Compare>
+size_t Map<Key, T, Compare>::erase(const key_type& key) {
+  iterator it = find(key);
+  if (it == end()) return 0;
+  erase(it);
+  return 1;
+}
+
+// TODO(mhaidry): Modify erase to use the iterator location
+// to create an efficient erase method
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::iterator Map<Key, T, Compare>::erase(
+    iterator iter) {
+  if (iter == end()) return iter;
+  key_type& del_key = iter->first;
+  Pair<iterator, Entry*> ret = RemoveRecursive(root_, del_key);
+  root_ = ret.second;
+  size_--;
+  return ret.first;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry* Map<Key, T, Compare>::InOrderSuccessor(
+    const Entry* e) const {
+  if (e->right != nullptr) {
+    return GetMinEntry(e->right);
+  }
+  Entry* successor = nullptr;
+  Entry* iter = root_;
+  while (iter != nullptr) {
+    int comp = CompareKeys(iter->pair.first, e->pair.first);
+    if (comp > 0) {
+      successor = iter;
+      iter = iter->left;
+    } else if (comp < 0) {
+      iter = iter->right;
+    } else
+      break;
+  }
+  return successor;
+}
+
+// Returns a pair with the first value being an iterator pointing to the
+// inserted entry and the second value being the new root of the subtree
+// after a rebalance
+template <class Key, class T, class Compare>
+typename ::grpc_core::Pair<typename Map<Key, T, Compare>::iterator,
+                           typename Map<Key, T, Compare>::Entry*>
+Map<Key, T, Compare>::InsertRecursive(Entry* root, value_type&& p) {
+  if (root == nullptr) {
+    Entry* e = New<Entry>(std::move(p));
+    return MakePair(iterator(this, e), e);
+  }
+  int comp = CompareKeys(root->pair.first, p.first);
+  if (comp > 0) {
+    Pair<iterator, Entry*> ret = InsertRecursive(root->left, std::move(p));
+    root->left = ret.second;
+    ret.second = RebalanceTreeAfterInsertion(root, ret.first->first);
+    return ret;
+  } else if (comp < 0) {
+    Pair<iterator, Entry*> ret = InsertRecursive(root->right, std::move(p));
+    root->right = ret.second;
+    ret.second = RebalanceTreeAfterInsertion(root, ret.first->first);
+    return ret;
+  } else {
+    root->pair = std::move(p);
+    return MakePair(iterator(this, root), root);
+  }
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry* Map<Key, T, Compare>::GetMinEntry(
+    Entry* e) {
+  if (e != nullptr) {
+    while (e->left != nullptr) {
+      e = e->left;
+    }
+  }
+  return e;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry* Map<Key, T, Compare>::RotateLeft(
+    Entry* e) {
+  Entry* rightChild = e->right;
+  Entry* rightLeftChild = rightChild->left;
+  rightChild->left = e;
+  e->right = rightLeftChild;
+  e->height = 1 + GPR_MAX(EntryHeight(e->left), EntryHeight(e->right));
+  rightChild->height = 1 + GPR_MAX(EntryHeight(rightChild->left),
+                                   EntryHeight(rightChild->right));
+  return rightChild;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry* Map<Key, T, Compare>::RotateRight(
+    Entry* e) {
+  Entry* leftChild = e->left;
+  Entry* leftRightChild = leftChild->right;
+  leftChild->right = e;
+  e->left = leftRightChild;
+  e->height = 1 + GPR_MAX(EntryHeight(e->left), EntryHeight(e->right));
+  leftChild->height =
+      1 + GPR_MAX(EntryHeight(leftChild->left), EntryHeight(leftChild->right));
+  return leftChild;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry*
+Map<Key, T, Compare>::RebalanceTreeAfterInsertion(Entry* root,
+                                                  const key_type& k) {
+  root->height = 1 + GPR_MAX(EntryHeight(root->left), EntryHeight(root->right));
+  int32_t heightDifference = EntryHeight(root->left) - EntryHeight(root->right);
+  if (heightDifference > 1 && CompareKeys(root->left->pair.first, k) > 0) {
+    return RotateRight(root);
+  }
+  if (heightDifference < -1 && CompareKeys(root->right->pair.first, k) < 0) {
+    return RotateLeft(root);
+  }
+  if (heightDifference > 1 && CompareKeys(root->left->pair.first, k) < 0) {
+    root->left = RotateLeft(root->left);
+    return RotateRight(root);
+  }
+  if (heightDifference < -1 && CompareKeys(root->right->pair.first, k) > 0) {
+    root->right = RotateRight(root->right);
+    return RotateLeft(root);
+  }
+  return root;
+}
+
+template <class Key, class T, class Compare>
+typename Map<Key, T, Compare>::Entry*
+Map<Key, T, Compare>::RebalanceTreeAfterDeletion(Entry* root) {
+  root->height = 1 + GPR_MAX(EntryHeight(root->left), EntryHeight(root->right));
+  int32_t heightDifference = EntryHeight(root->left) - EntryHeight(root->right);
+  if (heightDifference > 1) {
+    int leftHeightDifference =
+        EntryHeight(root->left->left) - EntryHeight(root->left->right);
+    if (leftHeightDifference < 0) {
+      root->left = RotateLeft(root->left);
+    }
+    return RotateRight(root);
+  }
+  if (heightDifference < -1) {
+    int rightHeightDifference =
+        EntryHeight(root->right->left) - EntryHeight(root->right->right);
+    if (rightHeightDifference > 0) {
+      root->right = RotateRight(root->right);
+    }
+    return RotateLeft(root);
+  }
+  return root;
+}
+
+template <class Key, class T, class Compare>
+typename ::grpc_core::Pair<typename Map<Key, T, Compare>::iterator,
+                           typename Map<Key, T, Compare>::Entry*>
+Map<Key, T, Compare>::RemoveRecursive(Entry* root, const key_type& k) {
+  Pair<iterator, Entry*> ret = MakePair(end(), root);
+  if (root == nullptr) return ret;
+  int comp = CompareKeys(root->pair.first, k);
+  if (comp > 0) {
+    ret = RemoveRecursive(root->left, k);
+    root->left = ret.second;
+  } else if (comp < 0) {
+    ret = RemoveRecursive(root->right, k);
+    root->right = ret.second;
+  } else {
+    Entry* entry;
+    Entry* successor = InOrderSuccessor(root);
+    if (root->left == nullptr) {
+      entry = root->right;
+      Delete(root);
+      return MakePair(iterator(this, successor), entry);
+    } else if (root->right == nullptr) {
+      entry = root->left;
+      Delete(root);
+      return MakePair(iterator(this, successor), entry);
+    } else {
+      entry = successor;
+      root->pair.swap(entry->pair);
+      ret = RemoveRecursive(root->right, entry->pair.first);
+      root->right = ret.second;
+      ret.first = iterator(this, root);
+    }
+  }
+  return MakePair(ret.first, RebalanceTreeAfterDeletion(root));
+}
+
+template <class Key, class T, class Compare>
+int Map<Key, T, Compare>::CompareKeys(const key_type& lhs,
+                                      const key_type& rhs) {
+  // This is a workaround for "const key_compare compare;"
+  // because some versions of compilers cannot build this by requiring
+  // a user-provided constructor. (ref: https://stackoverflow.com/q/7411515)
+  key_compare compare_tmp;
+  const key_compare& compare = compare_tmp;
+  bool left_comparison = compare(lhs, rhs);
+  bool right_comparison = compare(rhs, lhs);
+  // Both values are equal
+  if (!left_comparison && !right_comparison) {
+    return 0;
+  }
+  return left_comparison ? -1 : 1;
+}
+
+#endif  // GRPC_USE_CPP_STD_LIB
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_MAP_H */