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