]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 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_SRC_SBUF_ALGORITHMS_H | |
10 | #define SQUID_SRC_SBUF_ALGORITHMS_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 case-insensitive SBufs | |
116 | /// \sa std::hash<SBuf> | |
117 | class CaseInsensitiveSBufHash | |
118 | { | |
119 | public: | |
120 | std::size_t operator()(const SBuf &) const noexcept; | |
121 | }; | |
122 | ||
123 | /// equality functor for case-insensitive SBufs | |
124 | /// \sa std::equal_to<SBuf> | |
125 | class CaseInsensitiveSBufEqual | |
126 | { | |
127 | public: | |
128 | bool operator()(const SBuf &lhs, const SBuf &rhs) const | |
129 | { | |
130 | // Optimization: Do not iterate strings of different lengths. | |
131 | return lhs.length() == rhs.length() && (lhs.compare(rhs, caseInsensitive) == 0); | |
132 | } | |
133 | }; | |
134 | ||
135 | #endif /* SQUID_SRC_SBUF_ALGORITHMS_H */ | |
136 |