1 #if defined EXTERN
2 #undef EXTERN
3 #endif
4 #if defined SETMODULE
5 #define EXTERN
6 #else
7 #define EXTERN extern
8 #endif
9
10 #ifndef _SET_H_INCLUDED
11 #define _SET_H_INCLUDED
12
13 /*
14 *****************************************************************
15 *****************************************************************
16 ******* ********
17 ****** Copyright (C) 1988-2010 Tecplot, Inc. *******
18 ******* ********
19 *****************************************************************
20 *****************************************************************
21 */
22
23 #include <vector>
24 #include <algorithm>
25
26 #define PadOut(X,Y) ((int)(((X)-1)/(Y)+1)*(Y))
27 #define SetBitSize (8*sizeof(SetData_t))
28 #define SetLastBit (((unsigned long)1)<<(SetBitSize-1))
29
30 #if defined _DEBUG
31 # define USE_FUNCTIONS_FOR_SETS
32 #endif
33
34 /* *
35 * * NOTE: "Set_pa" is a pointer to an "abstract type",
36 * * hence the "_pa". Pointer here is akin to "handle".
37 * * Any routines dealing with the internals of Set_pa
38 * * or Set_a must be in the same file as these routines
39 * */
40
41 /* Set_a is intentionally not defined to further
42 * deter usage of this private structure */
43 struct _Set_a
44 {
45 /* * PRIVATE * */
46 SetIndex_t size;
47 SetData_pt data;
48 };
49
50 /*
51 * Checks set for NULL.
52 */
53 #define IsSetNull(Set) ((Set)==NULL)
54
55 /**
56 * Indicates how many bytes are required to store the set data.
57 */
SetDataSizeInBytes(Set_pa Set)58 inline size_t SetDataSizeInBytes(Set_pa Set)
59 {
60 REQUIRE(VALID_REF(Set));
61 return Set->size / SetBitSize * sizeof(SetData_t);
62 }
63
64 /*
65 * Allocates a new empty set. Returns NULL if not enough memory.
66 */
67 EXTERN Set_pa AllocSet(Boolean_t show_error_msg);
68
69 /*
70 * Frees all memory associated with set "*set", and
71 * sets "*set" to NULL.
72 */
73 EXTERN void DeallocSet(Set_pa *Set);
74
75 /**
76 * This function adapts the DeallocSet function to work with the
77 * ArrayList's deallocation callback.
78 */
79 EXTERN Boolean_t SetItemDestructor(void *ItemRef,
80 ArbParam_t ClientData);
81 /*
82 * Makes sure set "set" can hold at least "max_val" elements.
83 * Returns TRUE if successful, FALSE otherwise. A successful
84 * call to ExpandSet() guarentees that any calls to AddToSet()
85 * will be successful as long as the elements added are less
86 * than "max_val".
87 */
88 EXTERN Boolean_t ExpandSet(Set_pa Set,
89 SetIndex_t max_val,
90 Boolean_t show_error_msg);
91
92 /*
93 * Copies set "src" to set "dst". Returns TRUE if successful,
94 * FALSE if "src" contains elements it is unable to add to "dst".
95 */
96 EXTERN Boolean_t CopySet(Set_pa dst,
97 Set_pa src,
98 Boolean_t show_error_msg);
99
100 /*
101 * Appends set "src" to set "dst". Returns TRUE if successful,
102 * FALSE if "src" contains elements it is unable to add to "dst".
103 */
104 EXTERN Boolean_t AppendSet(Set_pa dst,
105 Set_pa src,
106 Boolean_t show_error_msg);
107 /*
108 * Empties the set "set".
109 */
110 EXTERN void ClearSet(Set_pa Set);
111
112 /*
113 * Adds "member" to set "set". Returns TRUE if successful,
114 * FALSE otherwise. AddToSet() can only return FALSE if
115 * "member" is greater than any previous member of "set" and
116 * also greater that any "max_val" set with ExpandSet().
117 */
118 #if defined USE_FUNCTIONS_FOR_SETS
119 EXTERN Boolean_t AddToSet(Set_pa Set,
120 SetIndex_t member,
121 Boolean_t show_error_msg);
122 #else
123 # if defined __cplusplus
AddToSet(Set_pa Set,SetIndex_t member,Boolean_t show_error_msg)124 inline Boolean_t AddToSet(Set_pa Set,
125 SetIndex_t member,
126 Boolean_t show_error_msg)
127 {
128 if (Set &&
129 (member + 1 <= Set->size ||
130 ExpandSet(Set, member + 1, show_error_msg)))
131 {
132 SetIndex_t word = member / SetBitSize;
133 SetData_t bit = (SetData_t)1 << (member % SetBitSize);
134 Set->data[word] |= bit;
135 return TRUE;
136 }
137 else
138 return FALSE;
139 } /* AddToSet() */
140 # else
141 # define AddToSet(Set,member,show_error_msg) \
142 (((Set) && \
143 ((member)+1 <= (Set)->size || \
144 ExpandSet((Set), (member)+1, (show_error_msg)))) \
145 ? (((Set)->data[(member) / SetBitSize] |= (SetData_t)1 << ((member) % SetBitSize)), TRUE) \
146 : FALSE)
147 # endif
148 #endif
149
150 /*
151 * Removes "member" from set "set".
152 */
153 EXTERN void RemoveFromSet(Set_pa Set,
154 SetIndex_t member);
155
156 EXTERN void DeleteSetMember(Set_pa Set,
157 SetIndex_t Member);
158 EXTERN Boolean_t InsertSetMember(Set_pa Set,
159 SetIndex_t Member,
160 Boolean_t ShowErrMsg);
161 /*
162 * Test for membership of "member" in set "set". This is the only
163 * function worth making into a macro or inline function.
164 */
165 #if defined USE_FUNCTIONS_FOR_SETS
166 EXTERN Boolean_t InSet(Set_pa Set,
167 SetIndex_t member);
168 #else
169 # if defined __cplusplus
InSet(Set_pa Set,SetIndex_t member)170 inline Boolean_t InSet(Set_pa Set,
171 SetIndex_t member)
172 {
173 if (Set && (0 <= member && member < Set->size))
174 {
175 SetIndex_t word = member / SetBitSize;
176 SetData_t bit = (SetData_t)1 << (member % SetBitSize);
177 return (Set->data[word]&bit) != 0;
178 }
179 else
180 return FALSE;
181 } /* InSet() */
182 # else
183 # define InSet(Set,member) ((Set && (0<=(member) && (member)<(Set)->size)) \
184 ? ((Set)->data[(member)/SetBitSize]&((SetData_t)1<<((member)%SetBitSize)))!=0 \
185 : FALSE)
186 # endif
187 #endif
188
189 /*
190 * Returns TRUE if set "set" is empty.
191 */
192 EXTERN Boolean_t IsEmpty(Set_pa Set);
193
194 /*
195 * Returns TRUE if Set has voids.
196 */
197 EXTERN Boolean_t HasVoids(Set_pa Set);
198
199 /*
200 * Returns number of members in Set "Set".
201 */
202 EXTERN SetIndex_t MemberCount(Set_pa Set);
203
204 /*
205 * Returns the next member in set "set" after member "start_at".
206 * Use "start_at" of BAD_ZV_VALUE to find first member.
207 */
208 EXTERN SetIndex_t GetNextMember(Set_pa Set,
209 SetIndex_t start_at);
210
211 /*
212 * Returns the previous member in set "set" before member
213 * "start_at". Use "start_at" of BAD_ZV_VALUE to find last member.
214 */
215 EXTERN SetIndex_t GetPrevMember(Set_pa Set,
216 SetIndex_t start_at);
217
218 /*
219 * Returns TRUE if sets are equal (have same members). FALSE otherwise.
220 */
221 EXTERN Boolean_t EqualSets(Set_pa set1,
222 Set_pa set2);
223
224 /*
225 * Returns TRUE if all members of childset are contained in parentset.
226 */
227 EXTERN Boolean_t IsSubSet(Set_pa childset,
228 Set_pa parentset);
229
230 EXTERN SetIndex_t MemberOffset(Set_pa Set,
231 SetIndex_t Member);
232
233 EXTERN SetIndex_t OffsetMember(Set_pa Set,
234 SetIndex_t Offset);
235
236
237 EXTERN Boolean_t CopySetMember(Set_pa DstSet,
238 SetIndex_t DstOffset,
239 Set_pa SrcSet,
240 SetIndex_t SrcOffset);
241
242 EXTERN void ShiftSet(Set_pa Set,
243 SetIndex_t ShiftPos1,
244 SetIndex_t ShiftPos2,
245 SetIndex_t ShiftAmount);
246
247
248 /*
249 * Handy macros
250 */
251 #define GetFirstSetMember(Set) (GetNextMember((Set), BAD_SET_VALUE))
252 #define GetLastSetMember(Set) (GetPrevMember((Set), BAD_SET_VALUE))
253
254 #define ForAllMembersInSet(Member, Set) \
255 for (Member = GetFirstSetMember((Set)); \
256 Member != BAD_SET_VALUE; \
257 Member = GetNextMember((Set), (Member)))
258 #define ForAllMembersInReversedSet(Member, Set) \
259 for (Member = GetLastSetMember((Set)); \
260 Member != BAD_SET_VALUE; \
261 Member = GetPrevMember((Set), (Member)))
262
263 namespace tecplot
264 {
265
266 /**
267 * Converts a set into a vector of set offsets.
268 * @templateparam T
269 * Type item in the set.
270 * @param itemSet
271 * Set of items to convert into a vector of set offsets.
272 * @return
273 * Vector of set offsets.
274 * @throws std::bad_alloc if insufficient resources are available to made the copy
275 */
276 template <typename T>
toVector(Set_pa itemSet)277 std::vector<T> toVector(Set_pa itemSet)
278 {
279 REQUIRE(VALID_REF(itemSet) || itemSet == 0);
280
281 std::vector<T> result;
282 size_t const count = MemberCount(itemSet);
283 if (count != 0)
284 {
285 result.reserve(count);
286 SetIndex_t item;
287 ForAllMembersInSet(item,itemSet)
288 result.push_back(static_cast<T>(item));
289 }
290
291 return result;
292 }
293
294 /**
295 * Converts a vector into a set offsets.
296 * @templateparam T
297 * Type item in the set.
298 * @param items
299 * Vector of elements of type T to convert to the set of offsets.
300 * @return
301 * Allocated Set of items with the elements converted from the vector.
302 * @throws std::bad_alloc if insufficient resources are available to made the copy
303 */
304 template <typename T>
toSet(std::vector<T> const & items)305 Set_pa toSet(std::vector<T> const& items)
306 {
307 Set_pa result = AllocSet(FALSE);
308 if (result == NULL)
309 throw std::bad_alloc();
310
311 if (!items.empty())
312 {
313 // locate the largest element, O(n)
314 typename std::vector<T>::const_iterator largest = std::max_element(items.begin(), items.end());
315
316 if (!ExpandSet(result, *largest + 1, FALSE))
317 {
318 DeallocSet(&result);
319 throw std::bad_alloc();
320 }
321
322 for (typename std::vector<T>::const_iterator item = items.begin();item != items.end();++item)
323 {
324 if (!AddToSet(result,static_cast<SetIndex_t>(*item),FALSE))
325 throw std::bad_alloc();
326 }
327 }
328
329 ENSURE(VALID_REF(result));
330 return result;
331 }
332
333 }
334
335 #endif // _SET_H_INCLUDED
336