Branch data Line data Source code
1 : : /* Copyright 2006 Savarese Software Research Corporation
2 : : *
3 : : * Licensed under the Apache License, Version 2.0 (the "License");
4 : : * you may not use this file except in compliance with the License.
5 : : * You may obtain a copy of the License at
6 : : *
7 : : * http://www.savarese.com/software/ApacheLicense-2.0
8 : : *
9 : : * Unless required by applicable law or agreed to in writing, software
10 : : * distributed under the License is distributed on an "AS IS" BASIS,
11 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : * See the License for the specific language governing permissions and
13 : : * limitations under the License.
14 : : */
15 : :
16 : : /**
17 : : * @file
18 : : * This header defines the GroupList class.
19 : : */
20 : :
21 : : #ifndef __SSRC_SPREAD_GROUP_LIST_H
22 : : #define __SSRC_SPREAD_GROUP_LIST_H
23 : :
24 : : #include <string>
25 : : #include <ostream>
26 : :
27 : : #include <ssrc/spread/detail/Buffer.h>
28 : :
29 : : // sp.h includes stddef.h, so we need to include it before sp.h in
30 : : // order to ensure it gets skipped while inside the Spread namespace.
31 : : #include <cstddef>
32 : :
33 : : __BEGIN_NS_SPREAD_INCLUDE
34 : : # include <sp.h>
35 : : /** This is an internal typedef not meant for use in end-user code. */
36 : : typedef char group_type[MAX_GROUP_NAME];
37 : : __END_NS_SPREAD_INCLUDE
38 : :
39 : : __BEGIN_NS_SSRC_SPREAD
40 : :
41 : : using std::string;
42 : :
43 : : enum {
44 : : /**
45 : : * Maximum number of characters in a private name. This is
46 : : * inconsistent with MaxSizeProcessName and MaxSizeGroupName
47 : : * (which are max + 1), but it's how the %Spread Toolkit does it;
48 : : * so we don't deviate, even though we'd rather they all be
49 : : * consistently defined as maximum values.
50 : : */
51 : : MaxSizePrivateName = MAX_PRIVATE_NAME,
52 : : /** Maximum number of characters in the name of a daemon process + 1. */
53 : : MaxSizeProcessName = MAX_PROC_NAME,
54 : : /** The maximum number of characters in a group name + 1. */
55 : : MaxSizeGroupName = MAX_GROUP_NAME,
56 : : /** The minimum value of a valid group name character. */
57 : : MinValidGroupNameChar = 36,
58 : : /** The maximum value of a valid group name character. */
59 : : MaxValidGroupNameChar = 126,
60 : : /** The value of the group name character separator. */
61 : : GroupNameSeparatorChar = 35
62 : : };
63 : :
64 : :
65 : : /**
66 : : * Splits a private group name into its private name and process name
67 : : * components. This functions assumes it is provided a valid private
68 : : * group name, otherwise its behavior is undefined.
69 : : *
70 : : * @param private_group The private group name to split.
71 : : * @return A std::pair<string,string> where the first element is the
72 : : * private name component and the second element is the process name
73 : : * component.
74 : : */
75 : : inline
76 : 21 : std::pair<string,string> split_private_group(const string & private_group) {
77 : 21 : string::size_type length = private_group.find(GroupNameSeparatorChar, 1) - 1;
78 [ + - ]: 42 : return std::pair<string,string>(string(private_group, 1, length),
79 : 42 : string(private_group, length + 2,
80 : 63 : private_group.size() - length - 2));
81 : : }
82 : :
83 : : /**
84 : : * GroupList is a container for %Spread group names. You use it to
85 : : * determine the destination of a message or ascertain membership
86 : : * information. A GroupList can be resized by its friend classes as
87 : : * needed so that you don't have to pre-allocate a very large list or
88 : : * handle short buffer errors.
89 : : */
90 : 37 : class GroupList {
91 : : private:
92 : : struct group_type {
93 : : Spread::group_type group;
94 : : };
95 : :
96 : : typedef detail::Buffer<group_type> group_vector;
97 : :
98 : : group_vector _groups;
99 : :
100 : 31 : const Spread::group_type *groups() const {
101 : 31 : return reinterpret_cast<const Spread::group_type *>(&_groups[0]);
102 : : }
103 : :
104 : 22 : Spread::group_type *groups() {
105 : : return
106 : 22 : const_cast<Spread::group_type *>(reinterpret_cast<const Spread::group_type *>(&_groups[0]));
107 : : }
108 : :
109 : 13 : unsigned int capacity() const {
110 : 13 : return _groups.capacity();
111 : : }
112 : :
113 : 34 : void resize(const unsigned int size) {
114 : 34 : _groups.resize(size);
115 : 34 : }
116 : :
117 : : public:
118 : :
119 : : /**
120 : : * Creates an empty GroupList with the specified initial capacity.
121 : : */
122 : 37 : explicit GroupList(const unsigned int capacity = 10) : _groups(capacity) { }
123 : :
124 : : /**
125 : : * Appends a group name to the list.
126 : : *
127 : : * @param group The group name to add.
128 : : */
129 : 19 : void add(const string & group) {
130 : : int size;
131 : : group_type gname;
132 [ + - ]: 19 : size = group.copy(gname.group, sizeof(Spread::group_type) - 1);
133 : 19 : gname.group[size] = 0;
134 [ + - ]: 19 : _groups.add(gname);
135 : 19 : }
136 : :
137 : : /**
138 : : * Appends the contents another GroupList to this one.
139 : : *
140 : : * @param groups The GroupList to append.
141 : : */
142 : 4 : void add(const GroupList & groups) {
143 [ + - ]: 4 : if(&groups != this) {
144 : 4 : unsigned int offset = size();
145 : 4 : resize(size() + groups.size());
146 : 4 : std::memcpy(GroupList::groups() + offset, groups.groups(),
147 : 8 : groups.size()*sizeof(group_type));
148 : : }
149 : 4 : }
150 : :
151 : : /**
152 : : * Returns the group name at the specified index. No bounds checking
153 : : * is performed; it is the responsibility of the caller to ensure a
154 : : * valid index is provided.
155 : : *
156 : : * @param index The index of the group name to return.
157 : : * @return The group name at the specified index.
158 : : */
159 : 8 : string group(const unsigned int index) const {
160 [ + - ]: 8 : return _groups[index].group;
161 : : }
162 : :
163 : : /** Same as {@link #group group(index)}. */
164 : 5 : string operator[](const unsigned int index) const {
165 : 5 : return group(index);
166 : : }
167 : :
168 : : /**
169 : : * Assigns the value of another GroupList to this one.
170 : : *
171 : : * @param groups The GroupList to copy.
172 : : * @return *this
173 : : */
174 : 4 : GroupList & operator=(const GroupList & groups) {
175 [ + - ]: 4 : if(&groups != this) {
176 : 4 : resize(groups.size());
177 : 4 : std::memcpy(GroupList::groups(), groups.groups(),
178 : 8 : size()*sizeof(group_type));
179 : : }
180 : 4 : return *this;
181 : : }
182 : :
183 : : /** Empties the list. */
184 : 14 : void clear() {
185 : 14 : _groups.clear();
186 : 14 : }
187 : :
188 : : /**
189 : : * Returns the number of groups in the list.
190 : : * @return The number of groups in the list.
191 : : */
192 : 66 : unsigned int size() const {
193 : 66 : return _groups.size();
194 : : }
195 : :
196 : : private:
197 : : friend class Mailbox;
198 : : friend class BaseMessage;
199 : :
200 : : /**
201 : : * Tests that two GroupLists contain the exact same number of groups
202 : : * with the exact same values in the exact same order. Use namespace
203 : : * std::rel_ops to gain the != operator.
204 : : *
205 : : * @param groups1 The first GroupList in the comparison.
206 : : * @param groups2 The second GroupList in the comparison.
207 : : * @return true if the GroupLists contain the same groups in the
208 : : * same order, false if not.
209 : : */
210 : 6 : friend bool operator==(const GroupList & groups1,
211 : : const GroupList & groups2)
212 : : {
213 : 6 : unsigned int size = groups1.size();
214 : :
215 [ + + ]: 6 : if(size != groups2.size())
216 : 2 : return false;
217 : : else
218 [ + + ]: 16 : while(size-- > 0) {
219 [ - + ]: 6 : if(std::strncmp(groups1.groups()[size], groups2.groups()[size],
220 : : MaxSizeGroupName))
221 : 0 : return false;
222 : : }
223 : :
224 : 4 : return true;
225 : : }
226 : :
227 : : /**
228 : : * Outputs the group names contained in the list—one per line.
229 : : *
230 : : * @param output The ostream to write to.
231 : : * @param groups The GroupList to output.
232 : : * @return The std::ostream output parameter.
233 : : */
234 : : friend std::ostream & operator<<(std::ostream & output,
235 : : const GroupList & groups)
236 : : {
237 : : for(unsigned int i = 0; i < groups.size(); ++i)
238 : : output << groups._groups[i].group << std::endl;
239 : : return output;
240 : : }
241 : : };
242 : :
243 : : __END_NS_SSRC_SPREAD
244 : :
245 : : #endif
|