1 /**
2  * WinPR: Windows Portable Runtime
3  * Collections
4  *
5  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef WINPR_COLLECTIONS_H
21 #define WINPR_COLLECTIONS_H
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <winpr/winpr.h>
28 #include <winpr/wtypes.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/stream.h>
33 
34 #ifdef __cplusplus
35 extern "C"
36 {
37 #endif
38 
39 	typedef void* (*OBJECT_NEW_FN)(void* val);
40 	typedef void (*OBJECT_INIT_FN)(void* obj);
41 	typedef void (*OBJECT_UNINIT_FN)(void* obj);
42 	typedef void (*OBJECT_FREE_FN)(void* obj);
43 	typedef BOOL (*OBJECT_EQUALS_FN)(const void* objA, const void* objB);
44 
45 	struct _wObject
46 	{
47 		OBJECT_NEW_FN fnObjectNew;
48 		OBJECT_INIT_FN fnObjectInit;
49 		OBJECT_UNINIT_FN fnObjectUninit;
50 		OBJECT_FREE_FN fnObjectFree;
51 		OBJECT_EQUALS_FN fnObjectEquals;
52 	};
53 	typedef struct _wObject wObject;
54 
55 	/* System.Collections.Queue */
56 
57 	struct _wQueue
58 	{
59 		int capacity;
60 		int growthFactor;
61 		BOOL synchronized;
62 
63 		int head;
64 		int tail;
65 		int size;
66 		void** array;
67 		CRITICAL_SECTION lock;
68 		HANDLE event;
69 
70 		wObject object;
71 	};
72 	typedef struct _wQueue wQueue;
73 
74 	WINPR_API int Queue_Count(wQueue* queue);
75 
76 	WINPR_API void Queue_Lock(wQueue* queue);
77 	WINPR_API void Queue_Unlock(wQueue* queue);
78 
79 	WINPR_API HANDLE Queue_Event(wQueue* queue);
80 
81 #define Queue_Object(_queue) (&_queue->object)
82 
83 	WINPR_API void Queue_Clear(wQueue* queue);
84 
85 	WINPR_API BOOL Queue_Contains(wQueue* queue, void* obj);
86 
87 	WINPR_API BOOL Queue_Enqueue(wQueue* queue, void* obj);
88 	WINPR_API void* Queue_Dequeue(wQueue* queue);
89 
90 	WINPR_API void* Queue_Peek(wQueue* queue);
91 
92 	WINPR_API wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor);
93 	WINPR_API void Queue_Free(wQueue* queue);
94 
95 	/* System.Collections.Stack */
96 
97 	struct _wStack
98 	{
99 		int size;
100 		int capacity;
101 		void** array;
102 		CRITICAL_SECTION lock;
103 		BOOL synchronized;
104 		wObject object;
105 	};
106 	typedef struct _wStack wStack;
107 
108 	WINPR_API int Stack_Count(wStack* stack);
109 	WINPR_API BOOL Stack_IsSynchronized(wStack* stack);
110 
111 #define Stack_Object(_stack) (&_stack->object)
112 
113 	WINPR_API void Stack_Clear(wStack* stack);
114 	WINPR_API BOOL Stack_Contains(wStack* stack, void* obj);
115 
116 	WINPR_API void Stack_Push(wStack* stack, void* obj);
117 	WINPR_API void* Stack_Pop(wStack* stack);
118 
119 	WINPR_API void* Stack_Peek(wStack* stack);
120 
121 	WINPR_API wStack* Stack_New(BOOL synchronized);
122 	WINPR_API void Stack_Free(wStack* stack);
123 
124 	/* System.Collections.ArrayList */
125 
126 	struct _wArrayList
127 	{
128 		int capacity;
129 		int growthFactor;
130 		BOOL synchronized;
131 
132 		int size;
133 		void** array;
134 		CRITICAL_SECTION lock;
135 
136 		wObject object;
137 	};
138 	typedef struct _wArrayList wArrayList;
139 
140 	WINPR_API int ArrayList_Capacity(wArrayList* arrayList);
141 	WINPR_API int ArrayList_Count(wArrayList* arrayList);
142 	WINPR_API int ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems);
143 	WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
144 	WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
145 	WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);
146 
147 	WINPR_API void ArrayList_Lock(wArrayList* arrayList);
148 	WINPR_API void ArrayList_Unlock(wArrayList* arrayList);
149 
150 	WINPR_API void* ArrayList_GetItem(wArrayList* arrayList, int index);
151 	WINPR_API void ArrayList_SetItem(wArrayList* arrayList, int index, void* obj);
152 
153 #define ArrayList_Object(_arrayList) (&_arrayList->object)
154 
155 #define ArrayList_ForEach(_lst, _type, index, value)                                       \
156 	for (index = 0;                                                                        \
157 	     index < ArrayList_Count(_lst) && (value = (_type)ArrayList_GetItem(_lst, index)); \
158 	     index++)
159 
160 	WINPR_API void ArrayList_Clear(wArrayList* arrayList);
161 	WINPR_API BOOL ArrayList_Contains(wArrayList* arrayList, void* obj);
162 
163 	WINPR_API int ArrayList_Add(wArrayList* arrayList, void* obj);
164 	WINPR_API BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj);
165 
166 	WINPR_API BOOL ArrayList_Remove(wArrayList* arrayList, void* obj);
167 	WINPR_API BOOL ArrayList_RemoveAt(wArrayList* arrayList, int index);
168 
169 	WINPR_API int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int count);
170 	WINPR_API int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex,
171 	                                    int count);
172 
173 	WINPR_API wArrayList* ArrayList_New(BOOL synchronized);
174 	WINPR_API void ArrayList_Free(wArrayList* arrayList);
175 
176 	/* System.Collections.DictionaryBase */
177 
178 	struct _wDictionary
179 	{
180 		BOOL synchronized;
181 		CRITICAL_SECTION lock;
182 	};
183 	typedef struct _wDictionary wDictionary;
184 
185 	/* System.Collections.Specialized.ListDictionary */
186 
187 	typedef struct _wListDictionaryItem wListDictionaryItem;
188 
189 	struct _wListDictionaryItem
190 	{
191 		void* key;
192 		void* value;
193 
194 		wListDictionaryItem* next;
195 	};
196 
197 	struct _wListDictionary
198 	{
199 		BOOL synchronized;
200 		CRITICAL_SECTION lock;
201 
202 		wListDictionaryItem* head;
203 		wObject objectKey;
204 		wObject objectValue;
205 	};
206 	typedef struct _wListDictionary wListDictionary;
207 
208 #define ListDictionary_KeyObject(_dictionary) (&_dictionary->objectKey)
209 #define ListDictionary_ValueObject(_dictionary) (&_dictionary->objectValue)
210 
211 	WINPR_API int ListDictionary_Count(wListDictionary* listDictionary);
212 
213 	WINPR_API void ListDictionary_Lock(wListDictionary* listDictionary);
214 	WINPR_API void ListDictionary_Unlock(wListDictionary* listDictionary);
215 
216 	WINPR_API BOOL ListDictionary_Add(wListDictionary* listDictionary, const void* key,
217 	                                  void* value);
218 	WINPR_API void* ListDictionary_Remove(wListDictionary* listDictionary, const void* key);
219 	WINPR_API void* ListDictionary_Remove_Head(wListDictionary* listDictionary);
220 	WINPR_API void ListDictionary_Clear(wListDictionary* listDictionary);
221 
222 	WINPR_API BOOL ListDictionary_Contains(wListDictionary* listDictionary, const void* key);
223 	WINPR_API int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys);
224 
225 	WINPR_API void* ListDictionary_GetItemValue(wListDictionary* listDictionary, const void* key);
226 	WINPR_API BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, const void* key,
227 	                                           void* value);
228 
229 	WINPR_API wListDictionary* ListDictionary_New(BOOL synchronized);
230 	WINPR_API void ListDictionary_Free(wListDictionary* listDictionary);
231 
232 	/* System.Collections.Generic.LinkedList<T> */
233 
234 	typedef struct _wLinkedList wLinkedList;
235 
236 	WINPR_API int LinkedList_Count(wLinkedList* list);
237 	WINPR_API void* LinkedList_First(wLinkedList* list);
238 	WINPR_API void* LinkedList_Last(wLinkedList* list);
239 
240 	WINPR_API BOOL LinkedList_Contains(wLinkedList* list, void* value);
241 	WINPR_API void LinkedList_Clear(wLinkedList* list);
242 
243 	WINPR_API BOOL LinkedList_AddFirst(wLinkedList* list, void* value);
244 	WINPR_API BOOL LinkedList_AddLast(wLinkedList* list, void* value);
245 
246 	WINPR_API BOOL LinkedList_Remove(wLinkedList* list, void* value);
247 	WINPR_API void LinkedList_RemoveFirst(wLinkedList* list);
248 	WINPR_API void LinkedList_RemoveLast(wLinkedList* list);
249 
250 	WINPR_API void LinkedList_Enumerator_Reset(wLinkedList* list);
251 	WINPR_API void* LinkedList_Enumerator_Current(wLinkedList* list);
252 	WINPR_API BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list);
253 
254 	WINPR_API wLinkedList* LinkedList_New(void);
255 	WINPR_API void LinkedList_Free(wLinkedList* list);
256 
257 	WINPR_API wObject* LinkedList_Object(wLinkedList* list);
258 
259 	/* System.Collections.Generic.KeyValuePair<TKey,TValue> */
260 
261 	typedef struct _wKeyValuePair wKeyValuePair;
262 
263 	struct _wKeyValuePair
264 	{
265 		void* key;
266 		void* value;
267 
268 		wKeyValuePair* next;
269 	};
270 
271 	/* Reference Table */
272 
273 	struct _wReference
274 	{
275 		UINT32 Count;
276 		void* Pointer;
277 	};
278 	typedef struct _wReference wReference;
279 
280 	typedef int (*REFERENCE_FREE)(void* context, void* ptr);
281 
282 	struct _wReferenceTable
283 	{
284 		UINT32 size;
285 		CRITICAL_SECTION lock;
286 		void* context;
287 		BOOL synchronized;
288 		wReference* array;
289 		REFERENCE_FREE ReferenceFree;
290 	};
291 	typedef struct _wReferenceTable wReferenceTable;
292 
293 	WINPR_API UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr);
294 	WINPR_API UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr);
295 
296 	WINPR_API wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context,
297 	                                              REFERENCE_FREE ReferenceFree);
298 	WINPR_API void ReferenceTable_Free(wReferenceTable* referenceTable);
299 
300 	/* Countdown Event */
301 
302 	struct _wCountdownEvent
303 	{
304 		DWORD count;
305 		CRITICAL_SECTION lock;
306 		HANDLE event;
307 		DWORD initialCount;
308 	};
309 	typedef struct _wCountdownEvent wCountdownEvent;
310 
311 	WINPR_API DWORD CountdownEvent_CurrentCount(wCountdownEvent* countdown);
312 	WINPR_API DWORD CountdownEvent_InitialCount(wCountdownEvent* countdown);
313 	WINPR_API BOOL CountdownEvent_IsSet(wCountdownEvent* countdown);
314 	WINPR_API HANDLE CountdownEvent_WaitHandle(wCountdownEvent* countdown);
315 
316 	WINPR_API void CountdownEvent_AddCount(wCountdownEvent* countdown, DWORD signalCount);
317 	WINPR_API BOOL CountdownEvent_Signal(wCountdownEvent* countdown, DWORD signalCount);
318 	WINPR_API void CountdownEvent_Reset(wCountdownEvent* countdown, DWORD count);
319 
320 	WINPR_API wCountdownEvent* CountdownEvent_New(DWORD initialCount);
321 	WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown);
322 
323 	/* Hash Table */
324 
325 	typedef UINT32 (*HASH_TABLE_HASH_FN)(void* key);
326 	typedef BOOL (*HASH_TABLE_KEY_COMPARE_FN)(void* key1, void* key2);
327 	typedef BOOL (*HASH_TABLE_VALUE_COMPARE_FN)(void* value1, void* value2);
328 	typedef void* (*HASH_TABLE_KEY_CLONE_FN)(void* key);
329 	typedef void* (*HASH_TABLE_VALUE_CLONE_FN)(void* value);
330 	typedef void (*HASH_TABLE_KEY_FREE_FN)(void* key);
331 	typedef void (*HASH_TABLE_VALUE_FREE_FN)(void* value);
332 
333 	struct _wHashTable
334 	{
335 		BOOL synchronized;
336 		CRITICAL_SECTION lock;
337 
338 		int numOfBuckets;
339 		int numOfElements;
340 		float idealRatio;
341 		float lowerRehashThreshold;
342 		float upperRehashThreshold;
343 		wKeyValuePair** bucketArray;
344 
345 		HASH_TABLE_HASH_FN hash;
346 		HASH_TABLE_KEY_COMPARE_FN keyCompare;
347 		HASH_TABLE_VALUE_COMPARE_FN valueCompare;
348 		HASH_TABLE_KEY_CLONE_FN keyClone;
349 		HASH_TABLE_VALUE_CLONE_FN valueClone;
350 		HASH_TABLE_KEY_FREE_FN keyFree;
351 		HASH_TABLE_VALUE_FREE_FN valueFree;
352 	};
353 	typedef struct _wHashTable wHashTable;
354 
355 	WINPR_API int HashTable_Count(wHashTable* table);
356 	WINPR_API int HashTable_Add(wHashTable* table, void* key, void* value);
357 	WINPR_API BOOL HashTable_Remove(wHashTable* table, void* key);
358 	WINPR_API void HashTable_Clear(wHashTable* table);
359 	WINPR_API BOOL HashTable_Contains(wHashTable* table, void* key);
360 	WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key);
361 	WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value);
362 	WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key);
363 	WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value);
364 	WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
365 
366 	WINPR_API UINT32 HashTable_PointerHash(void* pointer);
367 	WINPR_API BOOL HashTable_PointerCompare(void* pointer1, void* pointer2);
368 
369 	WINPR_API UINT32 HashTable_StringHash(void* key);
370 	WINPR_API BOOL HashTable_StringCompare(void* string1, void* string2);
371 	WINPR_API void* HashTable_StringClone(void* str);
372 	WINPR_API void HashTable_StringFree(void* str);
373 
374 	WINPR_API wHashTable* HashTable_New(BOOL synchronized);
375 	WINPR_API void HashTable_Free(wHashTable* table);
376 
377 	/* BufferPool */
378 
379 	struct _wBufferPoolItem
380 	{
381 		int size;
382 		void* buffer;
383 	};
384 	typedef struct _wBufferPoolItem wBufferPoolItem;
385 
386 	struct _wBufferPool
387 	{
388 		int fixedSize;
389 		DWORD alignment;
390 		BOOL synchronized;
391 		CRITICAL_SECTION lock;
392 
393 		int size;
394 		int capacity;
395 		void** array;
396 
397 		int aSize;
398 		int aCapacity;
399 		wBufferPoolItem* aArray;
400 
401 		int uSize;
402 		int uCapacity;
403 		wBufferPoolItem* uArray;
404 	};
405 	typedef struct _wBufferPool wBufferPool;
406 
407 	WINPR_API int BufferPool_GetPoolSize(wBufferPool* pool);
408 	WINPR_API int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer);
409 
410 	WINPR_API void* BufferPool_Take(wBufferPool* pool, int bufferSize);
411 	WINPR_API BOOL BufferPool_Return(wBufferPool* pool, void* buffer);
412 	WINPR_API void BufferPool_Clear(wBufferPool* pool);
413 
414 	WINPR_API wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment);
415 	WINPR_API void BufferPool_Free(wBufferPool* pool);
416 
417 	/* ObjectPool */
418 
419 	struct _wObjectPool
420 	{
421 		int size;
422 		int capacity;
423 		void** array;
424 		CRITICAL_SECTION lock;
425 		wObject object;
426 		BOOL synchronized;
427 	};
428 	typedef struct _wObjectPool wObjectPool;
429 
430 	WINPR_API void* ObjectPool_Take(wObjectPool* pool);
431 	WINPR_API void ObjectPool_Return(wObjectPool* pool, void* obj);
432 	WINPR_API void ObjectPool_Clear(wObjectPool* pool);
433 
434 #define ObjectPool_Object(_pool) (&_pool->object)
435 
436 	WINPR_API wObjectPool* ObjectPool_New(BOOL synchronized);
437 	WINPR_API void ObjectPool_Free(wObjectPool* pool);
438 
439 	/* Message Queue */
440 
441 	typedef struct _wMessage wMessage;
442 
443 	typedef void (*MESSAGE_FREE_FN)(wMessage* message);
444 
445 	struct _wMessage
446 	{
447 		UINT32 id;
448 		void* context;
449 		void* wParam;
450 		void* lParam;
451 		UINT64 time;
452 		MESSAGE_FREE_FN Free;
453 	};
454 
455 	struct _wMessageQueue
456 	{
457 		int head;
458 		int tail;
459 		int size;
460 		int capacity;
461 		wMessage* array;
462 		CRITICAL_SECTION lock;
463 		HANDLE event;
464 
465 		wObject object;
466 	};
467 	typedef struct _wMessageQueue wMessageQueue;
468 
469 #define WMQ_QUIT 0xFFFFFFFF
470 
471 	WINPR_API HANDLE MessageQueue_Event(wMessageQueue* queue);
472 	WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
473 	WINPR_API int MessageQueue_Size(wMessageQueue* queue);
474 
475 	WINPR_API BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message);
476 	WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam,
477 	                                 void* lParam);
478 	WINPR_API BOOL MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
479 
480 	WINPR_API int MessageQueue_Get(wMessageQueue* queue, wMessage* message);
481 	WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove);
482 
483 	/*! \brief Clears all elements in a message queue.
484 	 *
485 	 *  \note If dynamically allocated data is part of the messages,
486 	 *        a custom cleanup handler must be passed in the 'callback'
487 	 *        argument for MessageQueue_New.
488 	 *
489 	 *  \param queue The queue to clear.
490 	 *
491 	 *  \return 0 in case of success or a error code otherwise.
492 	 */
493 	WINPR_API int MessageQueue_Clear(wMessageQueue* queue);
494 
495 	/*! \brief Creates a new message queue.
496 	 * 				 If 'callback' is null, no custom cleanup will be done
497 	 * 				 on message queue deallocation.
498 	 * 				 If the 'callback' argument contains valid uninit or
499 	 * 				 free functions those will be called by
500 	 * 				 'MessageQueue_Clear'.
501 	 *
502 	 * \param callback a pointer to custom initialization / cleanup functions.
503 	 * 								 Can be NULL if not used.
504 	 *
505 	 * \return A pointer to a newly allocated MessageQueue or NULL.
506 	 */
507 	WINPR_API wMessageQueue* MessageQueue_New(const wObject* callback);
508 
509 	/*! \brief Frees resources allocated by a message queue.
510 	 * 				 This function will only free resources allocated
511 	 *				 internally.
512 	 *
513 	 * \note Empty the queue before calling this function with
514 	 * 			 'MessageQueue_Clear', 'MessageQueue_Get' or
515 	 * 			 'MessageQueue_Peek' to free all resources allocated
516 	 * 			 by the message contained.
517 	 *
518 	 * \param queue A pointer to the queue to be freed.
519 	 */
520 	WINPR_API void MessageQueue_Free(wMessageQueue* queue);
521 
522 	/* Message Pipe */
523 
524 	struct _wMessagePipe
525 	{
526 		wMessageQueue* In;
527 		wMessageQueue* Out;
528 	};
529 	typedef struct _wMessagePipe wMessagePipe;
530 
531 	WINPR_API void MessagePipe_PostQuit(wMessagePipe* pipe, int nExitCode);
532 
533 	WINPR_API wMessagePipe* MessagePipe_New(void);
534 	WINPR_API void MessagePipe_Free(wMessagePipe* pipe);
535 
536 	/* Publisher/Subscriber Pattern */
537 
538 	struct _wEventArgs
539 	{
540 		DWORD Size;
541 		const char* Sender;
542 	};
543 	typedef struct _wEventArgs wEventArgs;
544 
545 	typedef void (*pEventHandler)(void* context, wEventArgs* e);
546 
547 #define MAX_EVENT_HANDLERS 32
548 
549 	struct _wEventType
550 	{
551 		const char* EventName;
552 		wEventArgs EventArgs;
553 		int EventHandlerCount;
554 		pEventHandler EventHandlers[MAX_EVENT_HANDLERS];
555 	};
556 	typedef struct _wEventType wEventType;
557 
558 #define EventArgsInit(_event_args, _sender)                  \
559 	memset(_event_args, 0, sizeof(*_event_args));            \
560 	((wEventArgs*)_event_args)->Size = sizeof(*_event_args); \
561 	((wEventArgs*)_event_args)->Sender = _sender
562 
563 #define DEFINE_EVENT_HANDLER(_name) \
564 	typedef void (*p##_name##EventHandler)(void* context, _name##EventArgs* e)
565 
566 #define DEFINE_EVENT_RAISE(_name)                                                           \
567 	static INLINE int PubSub_On##_name(wPubSub* pubSub, void* context, _name##EventArgs* e) \
568 	{                                                                                       \
569 		return PubSub_OnEvent(pubSub, #_name, context, (wEventArgs*)e);                     \
570 	}
571 
572 #define DEFINE_EVENT_SUBSCRIBE(_name)                                              \
573 	static INLINE int PubSub_Subscribe##_name(wPubSub* pubSub,                     \
574 	                                          p##_name##EventHandler EventHandler) \
575 	{                                                                              \
576 		return PubSub_Subscribe(pubSub, #_name, (pEventHandler)EventHandler);      \
577 	}
578 
579 #define DEFINE_EVENT_UNSUBSCRIBE(_name)                                              \
580 	static INLINE int PubSub_Unsubscribe##_name(wPubSub* pubSub,                     \
581 	                                            p##_name##EventHandler EventHandler) \
582 	{                                                                                \
583 		return PubSub_Unsubscribe(pubSub, #_name, (pEventHandler)EventHandler);      \
584 	}
585 
586 #define DEFINE_EVENT_BEGIN(_name)      \
587 	typedef struct _##_name##EventArgs \
588 	{                                  \
589 		wEventArgs e;
590 
591 #define DEFINE_EVENT_END(_name)   \
592 	}                             \
593 	_name##EventArgs;             \
594 	DEFINE_EVENT_HANDLER(_name);  \
595 	DEFINE_EVENT_RAISE(_name)     \
596 	DEFINE_EVENT_SUBSCRIBE(_name) \
597 	DEFINE_EVENT_UNSUBSCRIBE(_name)
598 
599 #define DEFINE_EVENT_ENTRY(_name) { #_name, { sizeof(_name##EventArgs), NULL }, 0, { NULL } },
600 
601 	struct _wPubSub
602 	{
603 		CRITICAL_SECTION lock;
604 		BOOL synchronized;
605 
606 		int size;
607 		int count;
608 		wEventType* events;
609 	};
610 	typedef struct _wPubSub wPubSub;
611 
612 	WINPR_API void PubSub_Lock(wPubSub* pubSub);
613 	WINPR_API void PubSub_Unlock(wPubSub* pubSub);
614 
615 	WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count);
616 	WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count);
617 	WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
618 
619 	WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName,
620 	                               pEventHandler EventHandler);
621 	WINPR_API int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName,
622 	                                 pEventHandler EventHandler);
623 
624 	WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context,
625 	                             wEventArgs* e);
626 
627 	WINPR_API wPubSub* PubSub_New(BOOL synchronized);
628 	WINPR_API void PubSub_Free(wPubSub* pubSub);
629 
630 	/* BipBuffer */
631 
632 	struct _wBipBlock
633 	{
634 		size_t index;
635 		size_t size;
636 	};
637 	typedef struct _wBipBlock wBipBlock;
638 
639 	struct _wBipBuffer
640 	{
641 		size_t size;
642 		BYTE* buffer;
643 		size_t pageSize;
644 		wBipBlock blockA;
645 		wBipBlock blockB;
646 		wBipBlock readR;
647 		wBipBlock writeR;
648 	};
649 	typedef struct _wBipBuffer wBipBuffer;
650 
651 	WINPR_API BOOL BipBuffer_Grow(wBipBuffer* bb, size_t size);
652 	WINPR_API void BipBuffer_Clear(wBipBuffer* bb);
653 
654 	WINPR_API size_t BipBuffer_UsedSize(wBipBuffer* bb);
655 	WINPR_API size_t BipBuffer_BufferSize(wBipBuffer* bb);
656 
657 	WINPR_API BYTE* BipBuffer_WriteReserve(wBipBuffer* bb, size_t size);
658 	WINPR_API BYTE* BipBuffer_WriteTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
659 	WINPR_API void BipBuffer_WriteCommit(wBipBuffer* bb, size_t size);
660 
661 	WINPR_API BYTE* BipBuffer_ReadReserve(wBipBuffer* bb, size_t size);
662 	WINPR_API BYTE* BipBuffer_ReadTryReserve(wBipBuffer* bb, size_t size, size_t* reserved);
663 	WINPR_API void BipBuffer_ReadCommit(wBipBuffer* bb, size_t size);
664 
665 	WINPR_API SSIZE_T BipBuffer_Read(wBipBuffer* bb, BYTE* data, size_t size);
666 	WINPR_API SSIZE_T BipBuffer_Write(wBipBuffer* bb, const BYTE* data, size_t size);
667 
668 	WINPR_API wBipBuffer* BipBuffer_New(size_t size);
669 	WINPR_API void BipBuffer_Free(wBipBuffer* bb);
670 
671 #ifdef __cplusplus
672 }
673 #endif
674 
675 #endif /* WINPR_COLLECTIONS_H */
676