blob: e459727696adade9d465c1e9304879c9ff6b444c [file] [log] [blame]
Jordan Bayles8ccb4852019-01-16 18:51:27 -08001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Jordan Baylesa26582d2019-07-10 14:44:58 -07005#ifndef UTIL_STD_UTIL_H_
6#define UTIL_STD_UTIL_H_
Jordan Bayles8ccb4852019-01-16 18:51:27 -08007
mark a. foltz044f2542021-09-22 17:29:43 -07008#include <stddef.h>
9
Ryan Keane03e75032020-06-17 17:04:34 -070010#include <algorithm>
Jordan Bayles8ccb4852019-01-16 18:51:27 -080011#include <map>
Jordan Bayles067ccaf2019-06-07 10:03:02 -070012#include <string>
Ryan Keane03e75032020-06-17 17:04:34 -070013#include <utility>
Jordan Bayles05ce6b62019-09-06 14:09:10 -070014#include <vector>
Jordan Bayles8ccb4852019-01-16 18:51:27 -080015
Yuri Wiitalac5b90172019-04-15 15:42:30 -070016#include "absl/algorithm/container.h"
Jordan Bayles12b95e72020-12-03 09:26:47 -080017#include "util/stringprintf.h"
Yuri Wiitalac5b90172019-04-15 15:42:30 -070018
Jordan Bayles8ccb4852019-01-16 18:51:27 -080019namespace openscreen {
20
Max Yakimakha349c2aa2019-09-09 11:01:34 -070021template <typename T, size_t N>
22constexpr size_t countof(T (&array)[N]) {
23 return N;
24}
25
Jordan Bayles067ccaf2019-06-07 10:03:02 -070026// std::basic_string::data() has no mutable overload prior to C++17 [1].
27// Hence this overload is provided.
28// Note: str[0] is safe even for empty strings, as they are guaranteed to be
29// null-terminated [2].
30//
31// [1] http://en.cppreference.com/w/cpp/string/basic_string/data
32// [2] http://en.cppreference.com/w/cpp/string/basic_string/operator_at
33template <typename CharT, typename Traits, typename Allocator>
34CharT* data(std::basic_string<CharT, Traits, Allocator>& str) {
35 return std::addressof(str[0]);
36}
37
Jordan Bayles12b95e72020-12-03 09:26:47 -080038std::string Join(const std::vector<std::string>& strings,
39 const char* delimiter);
40
Jordan Bayles8ccb4852019-01-16 18:51:27 -080041template <typename Key, typename Value>
42void RemoveValueFromMap(std::map<Key, Value*>* map, Value* value) {
43 for (auto it = map->begin(); it != map->end();) {
44 if (it->second == value) {
45 it = map->erase(it);
46 } else {
47 ++it;
48 }
49 }
50}
51
Yuri Wiitalac5b90172019-04-15 15:42:30 -070052template <typename ForwardIteratingContainer>
53bool AreElementsSortedAndUnique(const ForwardIteratingContainer& c) {
54 return absl::c_is_sorted(c) && (absl::c_adjacent_find(c) == c.end());
55}
56
57template <typename RandomAccessContainer>
58void SortAndDedupeElements(RandomAccessContainer* c) {
59 std::sort(c->begin(), c->end());
60 const auto new_end = std::unique(c->begin(), c->end());
61 c->erase(new_end, c->end());
62}
63
Ryan Keane03e75032020-06-17 17:04:34 -070064// Append the provided elements together into a single vector. This can be
65// useful when creating a vector of variadic templates in the ctor.
66//
67// This is the base case for the recursion
68template <typename T>
69std::vector<T>&& Append(std::vector<T>&& so_far) {
70 return std::move(so_far);
71}
72
73// This is the recursive call. Depending on the number of remaining elements, it
74// either calls into itself or into the above base case.
75template <typename T, typename TFirst, typename... TOthers>
76std::vector<T>&& Append(std::vector<T>&& so_far,
77 TFirst&& new_element,
78 TOthers&&... new_elements) {
79 so_far.push_back(std::move(new_element));
80 return Append(std::move(so_far), std::move(new_elements)...);
81}
82
83// Creates an empty vector with |size| elements reserved. Intended to be used as
84// GetEmptyVectorOfSize<T>(sizeof...(variadic_input))
85template <typename T>
86std::vector<T> GetVectorWithCapacity(size_t size) {
87 std::vector<T> results;
88 results.reserve(size);
89 return results;
90}
91
mark a. foltz044f2542021-09-22 17:29:43 -070092// Returns true if an element equal to |element| is found in |container|.
93// C.begin() must return an iterator to the beginning of C and C.end() must
94// return an iterator to the end.
95template <typename C, typename E>
96bool Contains(const C& container, const E& element) {
97 return std::find(container.begin(), container.end(), element) !=
98 container.end();
99}
100
101// Returns true if any element in |container| returns true for |predicate|.
102// C.begin() must return an iterator to the beginning of C and C.end() must
103// return an iterator to the end.
104template <typename C, typename P>
105bool ContainsIf(const C& container, P predicate) {
106 return std::find_if(container.begin(), container.end(),
107 std::move(predicate)) != container.end();
108}
109
Jordan Bayles8ccb4852019-01-16 18:51:27 -0800110} // namespace openscreen
111
Jordan Baylesa26582d2019-07-10 14:44:58 -0700112#endif // UTIL_STD_UTIL_H_