]> git.ipfire.org Git - thirdparty/squid.git/blob - src/sbuf/Algorithms.h
d7159fa9e55ebcebf88576216f8837889d5f8a2c
[thirdparty/squid.git] / src / sbuf / Algorithms.h
1 /*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #ifndef SQUID_SBUFALGOS_H_
10 #define SQUID_SBUFALGOS_H_
11
12 #include "sbuf/SBuf.h"
13
14 #include <algorithm>
15 #include <numeric>
16
17 /// SBuf equality predicate for STL algorithms etc
18 class SBufEqual
19 {
20 public:
21 explicit SBufEqual(const SBuf &reference, SBufCaseSensitive sensitivity = caseSensitive) :
22 reference_(reference), sensitivity_(sensitivity) {}
23 bool operator() (const SBuf & checking) { return checking.compare(reference_,sensitivity_) == 0; }
24 private:
25 SBuf reference_;
26 SBufCaseSensitive sensitivity_;
27 };
28
29 /// SBuf "starts with" predicate for STL algorithms etc
30 class SBufStartsWith
31 {
32 public:
33 explicit SBufStartsWith(const SBuf &prefix, SBufCaseSensitive sensitivity = caseSensitive) :
34 prefix_(prefix), sensitivity_(sensitivity) {}
35 bool operator() (const SBuf & checking) { return checking.startsWith(prefix_,sensitivity_); }
36 private:
37 SBuf prefix_;
38 SBufCaseSensitive sensitivity_;
39 };
40
41 /** SBuf size addition accumulator for STL contaniners
42 *
43 * Equivalent to prefix_length + SBuf.length() + separator.length()
44 */
45 class SBufAddLength
46 {
47 public:
48 explicit SBufAddLength(const SBuf &separator) :
49 separatorLen_(separator.length()) {}
50 SBuf::size_type operator()(const SBuf::size_type sz, const SBuf & item) {
51 return sz + item.length() + separatorLen_;
52 }
53 private:
54 SBuf::size_type separatorLen_;
55 };
56
57 /** Join container of SBufs and append to supplied target
58 *
59 * append to the target SBuf all elements in the [begin,end) range from
60 * an iterable container, prefixed by prefix, separated by separator and
61 * followed by suffix. Prefix and suffix are added also in case of empty
62 * iterable
63 *
64 * \return the modified dest
65 */
66 template <class ContainerIterator>
67 SBuf&
68 JoinContainerIntoSBuf(SBuf &dest, const ContainerIterator &begin,
69 const ContainerIterator &end, const SBuf& separator,
70 const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
71 {
72 if (begin == end) {
73 dest.append(prefix).append(suffix);
74 return dest;
75 }
76
77 // optimization: pre-calculate needed storage
78 const SBuf::size_type totalContainerSize =
79 std::accumulate(begin, end, 0, SBufAddLength(separator)) +
80 dest.length() + prefix.length() + suffix.length();
81 SBufReservationRequirements req;
82 req.minSpace = totalContainerSize;
83 dest.reserve(req);
84
85 auto i = begin;
86 dest.append(prefix);
87 dest.append(*i);
88 ++i;
89 for (; i != end; ++i)
90 dest.append(separator).append(*i);
91 dest.append(suffix);
92 return dest;
93 }
94
95 /// convenience wrapper of JoinContainerIntoSBuf with no caller-supplied SBuf
96 template <class ContainerIterator>
97 SBuf
98 JoinContainerToSBuf(const ContainerIterator &begin,
99 const ContainerIterator &end, const SBuf& separator,
100 const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
101 {
102 SBuf rv;
103 return JoinContainerIntoSBuf(rv, begin, end, separator, prefix, suffix);
104 }
105
106 namespace std {
107 /// default hash functor to support std::unordered_map<SBuf,*>
108 template <>
109 struct hash<SBuf>
110 {
111 size_t operator()(const SBuf &) const noexcept;
112 };
113 }
114
115 /** hash functor for SBufs, meant so support case-insensitive std::unordered_map
116 *
117 * Typical use:
118 * \code
119 * auto m = std::unordered_map<SBuf, ValueType, CaseInsensitiveSBufHash>();
120 * \endcode
121 */
122 class CaseInsensitiveSBufHash
123 {
124 public:
125 std::size_t operator()(const SBuf &) const noexcept;
126 };
127
128 #endif /* SQUID_SBUFALGOS_H_ */
129