Line data Source code
1 : /*
2 : * Distributed under the OpenDDS License.
3 : * See: http://www.opendds.org/license.html
4 : */
5 :
6 : #ifndef OPENDDS_DCPS_UTIL_H
7 : #define OPENDDS_DCPS_UTIL_H
8 :
9 : #include <ace/CDR_Base.h>
10 :
11 : #include <cstring>
12 :
13 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
14 :
15 : namespace OpenDDS {
16 : namespace DCPS {
17 :
18 : // bind reproduces the ACE_Hash_Map_Manager_Ex's bind behavior
19 : template <typename Container, typename FirstType, typename SecondType>
20 0 : int bind(
21 : Container& c,
22 : const FirstType& first,
23 : const SecondType& second)
24 : {
25 0 : if (c.find(first) == c.end()) {
26 : typedef typename Container::value_type container_value_type;
27 :
28 0 : if (c.insert(container_value_type(first, second)).second) {
29 0 : return 0;
30 : }
31 :
32 0 : return -1;
33 : }
34 :
35 0 : return 1;
36 : }
37 :
38 : // unbind reproduces the ACE_Hash_Map_Manager_Ex's unbind behavior
39 : template <typename Container>
40 0 : int unbind(
41 : Container& c,
42 : const typename Container::key_type& k,
43 : typename Container::mapped_type& v)
44 : {
45 0 : typename Container::const_iterator iter = c.find(k);
46 :
47 0 : if (iter != c.end()) {
48 0 : v = iter->second;
49 :
50 0 : if (c.erase(k) == 1) {
51 0 : return 0;
52 : }
53 :
54 0 : return -1;
55 : }
56 :
57 0 : return -1;
58 : }
59 :
60 : // unbind reproduces the ACE_Hash_Map_Manager_Ex's unbind behavior
61 : template <typename Container>
62 0 : int unbind(
63 : Container& c,
64 : const typename Container::key_type& k)
65 : {
66 0 : typename Container::mapped_type v;
67 0 : return unbind(c, k, v);
68 0 : }
69 :
70 : template <typename Container, typename Key>
71 0 : int find(
72 : Container& c,
73 : const Key& key,
74 : typename Container::mapped_type*& value)
75 : {
76 : typename Container::iterator iter =
77 0 : c.find(key);
78 :
79 0 : if (iter == c.end()) {
80 0 : return -1;
81 : }
82 :
83 0 : value = &iter->second;
84 0 : return 0;
85 : }
86 :
87 : template <typename Container, typename Key>
88 0 : int find(
89 : const Container& c,
90 : const Key& key,
91 : typename Container::mapped_type& value)
92 : {
93 : typename Container::const_iterator iter =
94 0 : c.find(key);
95 :
96 0 : if (iter == c.end()) {
97 0 : return -1;
98 : }
99 :
100 0 : value = iter->second;
101 0 : return 0;
102 : }
103 :
104 : template <typename Container, typename ValueType>
105 0 : int insert(
106 : Container& c,
107 : const ValueType& v)
108 : {
109 0 : if (c.find(v) == c.end()) {
110 0 : if (c.insert(v).second) {
111 0 : return 0;
112 : }
113 :
114 0 : return -1;
115 : }
116 :
117 0 : return 1;
118 : }
119 :
120 : template <typename Container, typename ValueType>
121 0 : int remove(
122 : Container& c,
123 : const ValueType& v)
124 : {
125 0 : if (c.find(v) != c.end()) {
126 0 : if (c.erase(v) == 1) {
127 0 : return 0;
128 : }
129 :
130 0 : return -1;
131 : }
132 :
133 0 : return -1;
134 : }
135 :
136 : /// std::vector-style push_back() for CORBA Sequences
137 : template <typename Seq>
138 1759 : void push_back(Seq& seq, const typename Seq::value_type& val)
139 : {
140 1759 : const ACE_CDR::ULong len = seq.length();
141 : // Grow by factor of 2 when length is a power of 2 in order to prevent every call to length(+1)
142 : // allocating a new buffer & copying previous results. The maximum is kept when length is reduced.
143 1759 : if (len && !(len & (len - 1))) {
144 694 : seq.length(2 * len);
145 : }
146 1759 : seq.length(len + 1);
147 1759 : seq[len] = val;
148 1759 : }
149 :
150 : template <typename Seq>
151 33 : typename Seq::size_type grow(Seq& seq)
152 : {
153 33 : const ACE_CDR::ULong len = seq.length();
154 : // Grow by factor of 2 when length is a power of 2 in order to prevent every call to length(+1)
155 : // allocating a new buffer & copying previous results. The maximum is kept when length is reduced.
156 33 : if (len && !(len & (len - 1))) {
157 14 : seq.length(2 * len);
158 : }
159 33 : seq.length(len + 1);
160 33 : return len + 1;
161 : }
162 :
163 : // Constructs a sorted intersect of the given two sorted ranges [a,aEnd) and [b,bEnd).
164 : // (for pre-c++17 code for the similar effect of std::set_intersection in c++17)
165 : template <typename InputIteratorA, typename InputIteratorB, typename OutputIterator>
166 : OutputIterator intersect_sorted_ranges(InputIteratorA a, InputIteratorA aEnd,
167 : InputIteratorB b, InputIteratorB bEnd,
168 : OutputIterator intersect)
169 : {
170 : while (a != aEnd && b != bEnd) {
171 : if (*a < *b) { ++a; }
172 : else if (*b < *a) { ++b; }
173 : else { *intersect++ = *a++; ++b; }
174 : }
175 : return intersect;
176 : }
177 :
178 : // Constructs a sorted intersect of the given two sorted ranges [a,aEnd) and [b,bEnd).
179 : // (for pre-c++17 code for the similar effect of std::set_intersection in c++17)
180 : template <typename InputIteratorA, typename InputIteratorB, typename OutputIterator, typename LessThan>
181 0 : OutputIterator intersect_sorted_ranges(InputIteratorA a, InputIteratorA aEnd,
182 : InputIteratorB b, InputIteratorB bEnd,
183 : OutputIterator intersect, LessThan lessThan)
184 : {
185 0 : while (a != aEnd && b != bEnd) {
186 0 : if (lessThan(*a, *b)) { ++a; }
187 0 : else if (lessThan(*b, *a)) { ++b; }
188 0 : else { *intersect++ = *a++; ++b; }
189 : }
190 0 : return intersect;
191 : }
192 :
193 : // Keeps the intersection of the two sorted collections in the first one,
194 : // and returns whether an intersection exists between the two colloctions.
195 : // Note:
196 : // The generic scope of the first template parameter is narrowed down to std::set<T> because
197 : // the pre-c++11 erase() may not work here with some collections (e.g. a sorted std::vector).
198 : // The since-c++11 erase() works properly with both an std::set and a sorted std::vector.
199 : template <typename SetA, typename SortedB, typename LessThan>
200 : bool set_intersect(SetA& sA, const SortedB& sB, LessThan lessThan)
201 : {
202 : typename SetA::iterator a = sA.begin();
203 : typename SortedB::const_iterator b = sB.begin();
204 : while (a != sA.end()) {
205 : if (b != sB.end()) {
206 : if (lessThan(*a, *b)) {
207 : sA.erase(a++);
208 : } else {
209 : if (!lessThan(*b, *a)) { ++a; }
210 : ++b;
211 : }
212 : } else {
213 : sA.erase(a, sA.end());
214 : break;
215 : }
216 : }
217 : return !sA.empty();
218 : }
219 :
220 : template <typename Type, size_t count>
221 0 : size_t array_count(Type(&)[count])
222 : {
223 0 : return count;
224 : }
225 :
226 : template <typename T>
227 5026 : inline int mem_cmp(const T& a, const T& b)
228 : {
229 5026 : return std::memcmp(&a, &b, sizeof(T));
230 : }
231 :
232 : } // namespace DCPS
233 : } // namespace OpenDDS
234 :
235 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
236 :
237 : #endif /* OPENDDS_DCPS_UTIL_H */
|