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