FreeRDP/winpr/include/winpr/collections.h
2022-10-27 10:39:25 +02:00

576 lines
20 KiB
C

/**
* WinPR: Windows Portable Runtime
* Collections
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_COLLECTIONS_H
#define WINPR_COLLECTIONS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/assert.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef void* (*OBJECT_NEW_FN)(const void* val);
typedef void (*OBJECT_INIT_FN)(void* obj);
typedef void (*OBJECT_UNINIT_FN)(void* obj);
typedef void (*OBJECT_FREE_FN)(void* obj);
typedef BOOL (*OBJECT_EQUALS_FN)(const void* objA, const void* objB);
typedef struct
{
OBJECT_NEW_FN fnObjectNew;
OBJECT_INIT_FN fnObjectInit;
OBJECT_UNINIT_FN fnObjectUninit;
OBJECT_FREE_FN fnObjectFree;
OBJECT_EQUALS_FN fnObjectEquals;
} wObject;
/* System.Collections.Queue */
typedef struct s_wQueue wQueue;
WINPR_API size_t Queue_Count(wQueue* queue);
WINPR_API void Queue_Lock(wQueue* queue);
WINPR_API void Queue_Unlock(wQueue* queue);
WINPR_API HANDLE Queue_Event(wQueue* queue);
WINPR_API wObject* Queue_Object(wQueue* queue);
WINPR_API void Queue_Clear(wQueue* queue);
WINPR_API BOOL Queue_Contains(wQueue* queue, const void* obj);
/** \brief Pushes a new element into the queue.
* If a fnObjectNew is set, the element is copied and the queue takes
* ownership of the memory, otherwise the ownership stays with the caller.
*
* \param queue The queue to operate on
* \param obj A pointer to the object to queue
*
* \return TRUE for success, FALSE if failed.
*/
WINPR_API BOOL Queue_Enqueue(wQueue* queue, const void* obj);
/** \brief returns the element at the top of the queue. The element is removed from the queue,
* ownership of the element is passed on to the caller.
*
* \param queue The queue to check
*
* \return NULL if empty, a pointer to the memory on top of the queue otherwise.
*/
WINPR_API void* Queue_Dequeue(wQueue* queue);
/** \brief returns the element at the top of the queue. The element is not removed from the
* queue, ownership of the element stays with the queue.
*
* \param queue The queue to check
*
* \return NULL if empty, a pointer to the memory on top of the queue otherwise.
*/
WINPR_API void* Queue_Peek(wQueue* queue);
/** \brief Removes the element at the top of the queue. If fnObjectFree is set, the element is
* freed. This can be used in combination with Queue_Peek to handle an element and discard it
* with this function afterward. An alternative is Queue_Dequeue with calling the appropriate
* free function afterward.
*
* \param queue The queue to operate on
*/
WINPR_API void Queue_Discard(wQueue* queue);
WINPR_API wQueue* Queue_New(BOOL synchronized, SSIZE_T capacity, SSIZE_T growthFactor);
WINPR_API void Queue_Free(wQueue* queue);
/* System.Collections.Stack */
typedef struct s_wStack wStack;
WINPR_API size_t Stack_Count(wStack* stack);
WINPR_API BOOL Stack_IsSynchronized(wStack* stack);
WINPR_API wObject* Stack_Object(wStack* stack);
WINPR_API void Stack_Clear(wStack* stack);
WINPR_API BOOL Stack_Contains(wStack* stack, const void* obj);
WINPR_API void Stack_Push(wStack* stack, void* obj);
WINPR_API void* Stack_Pop(wStack* stack);
WINPR_API void* Stack_Peek(wStack* stack);
WINPR_API wStack* Stack_New(BOOL synchronized);
WINPR_API void Stack_Free(wStack* stack);
/* System.Collections.ArrayList */
typedef struct s_wArrayList wArrayList;
WINPR_API size_t ArrayList_Capacity(wArrayList* arrayList);
WINPR_API size_t ArrayList_Count(wArrayList* arrayList);
WINPR_API size_t ArrayList_Items(wArrayList* arrayList, ULONG_PTR** ppItems);
WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);
WINPR_API void ArrayList_Lock(wArrayList* arrayList);
WINPR_API void ArrayList_Unlock(wArrayList* arrayList);
WINPR_API void* ArrayList_GetItem(wArrayList* arrayList, size_t index);
WINPR_API BOOL ArrayList_SetItem(wArrayList* arrayList, size_t index, const void* obj);
WINPR_API wObject* ArrayList_Object(wArrayList* arrayList);
typedef BOOL (*ArrayList_ForEachFkt)(void* data, size_t index, va_list ap);
WINPR_API BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...);
WINPR_API BOOL ArrayList_ForEachAP(wArrayList* arrayList, ArrayList_ForEachFkt fkt, va_list ap);
WINPR_API void ArrayList_Clear(wArrayList* arrayList);
WINPR_API BOOL ArrayList_Contains(wArrayList* arrayList, const void* obj);
#if defined(WITH_WINPR_DEPRECATED)
WINPR_API WINPR_DEPRECATED(int ArrayList_Add(wArrayList* arrayList, const void* obj));
#endif
WINPR_API BOOL ArrayList_Append(wArrayList* arrayList, const void* obj);
WINPR_API BOOL ArrayList_Insert(wArrayList* arrayList, size_t index, const void* obj);
WINPR_API BOOL ArrayList_Remove(wArrayList* arrayList, const void* obj);
WINPR_API BOOL ArrayList_RemoveAt(wArrayList* arrayList, size_t index);
WINPR_API SSIZE_T ArrayList_IndexOf(wArrayList* arrayList, const void* obj, SSIZE_T startIndex,
SSIZE_T count);
WINPR_API SSIZE_T ArrayList_LastIndexOf(wArrayList* arrayList, const void* obj,
SSIZE_T startIndex, SSIZE_T count);
WINPR_API wArrayList* ArrayList_New(BOOL synchronized);
WINPR_API void ArrayList_Free(wArrayList* arrayList);
/* System.Collections.DictionaryBase */
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
typedef struct
{
BOOL synchronized;
CRITICAL_SECTION lock;
} wDictionary;
/* System.Collections.Specialized.ListDictionary */
typedef struct s_wListDictionaryItem wListDictionaryItem;
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
struct s_wListDictionaryItem
{
void* key;
void* value;
wListDictionaryItem* next;
};
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
typedef struct
{
BOOL synchronized;
CRITICAL_SECTION lock;
wListDictionaryItem* head;
wObject objectKey;
wObject objectValue;
} wListDictionary;
#define ListDictionary_KeyObject(_dictionary) (&_dictionary->objectKey)
#define ListDictionary_ValueObject(_dictionary) (&_dictionary->objectValue)
WINPR_API int ListDictionary_Count(wListDictionary* listDictionary);
WINPR_API void ListDictionary_Lock(wListDictionary* listDictionary);
WINPR_API void ListDictionary_Unlock(wListDictionary* listDictionary);
WINPR_API BOOL ListDictionary_Add(wListDictionary* listDictionary, const void* key,
void* value);
WINPR_API void* ListDictionary_Remove(wListDictionary* listDictionary, const void* key);
WINPR_API void* ListDictionary_Remove_Head(wListDictionary* listDictionary);
WINPR_API void ListDictionary_Clear(wListDictionary* listDictionary);
WINPR_API BOOL ListDictionary_Contains(wListDictionary* listDictionary, const void* key);
WINPR_API int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys);
WINPR_API void* ListDictionary_GetItemValue(wListDictionary* listDictionary, const void* key);
WINPR_API BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, const void* key,
void* value);
WINPR_API wListDictionary* ListDictionary_New(BOOL synchronized);
WINPR_API void ListDictionary_Free(wListDictionary* listDictionary);
/* System.Collections.Generic.LinkedList<T> */
typedef struct s_wLinkedList wLinkedList;
WINPR_API int LinkedList_Count(wLinkedList* list);
WINPR_API void* LinkedList_First(wLinkedList* list);
WINPR_API void* LinkedList_Last(wLinkedList* list);
WINPR_API BOOL LinkedList_Contains(wLinkedList* list, const void* value);
WINPR_API void LinkedList_Clear(wLinkedList* list);
WINPR_API BOOL LinkedList_AddFirst(wLinkedList* list, const void* value);
WINPR_API BOOL LinkedList_AddLast(wLinkedList* list, const void* value);
WINPR_API BOOL LinkedList_Remove(wLinkedList* list, const void* value);
WINPR_API void LinkedList_RemoveFirst(wLinkedList* list);
WINPR_API void LinkedList_RemoveLast(wLinkedList* list);
WINPR_API void LinkedList_Enumerator_Reset(wLinkedList* list);
WINPR_API void* LinkedList_Enumerator_Current(wLinkedList* list);
WINPR_API BOOL LinkedList_Enumerator_MoveNext(wLinkedList* list);
WINPR_API wLinkedList* LinkedList_New(void);
WINPR_API void LinkedList_Free(wLinkedList* list);
WINPR_API wObject* LinkedList_Object(wLinkedList* list);
/* System.Collections.Generic.KeyValuePair<TKey,TValue> */
/* Reference Table */
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
typedef struct
{
UINT32 Count;
void* Pointer;
} wReference;
typedef int (*REFERENCE_FREE)(void* context, void* ptr);
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
typedef struct
{
UINT32 size;
CRITICAL_SECTION lock;
void* context;
BOOL synchronized;
wReference* array;
REFERENCE_FREE ReferenceFree;
} wReferenceTable;
WINPR_API UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr);
WINPR_API UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr);
WINPR_API wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context,
REFERENCE_FREE ReferenceFree);
WINPR_API void ReferenceTable_Free(wReferenceTable* referenceTable);
/* Countdown Event */
/* WARNING: Do not access structs directly, the API will be reworked
* to make this opaque. */
typedef struct
{
DWORD count;
CRITICAL_SECTION lock;
HANDLE event;
DWORD initialCount;
} wCountdownEvent;
WINPR_API DWORD CountdownEvent_CurrentCount(wCountdownEvent* countdown);
WINPR_API DWORD CountdownEvent_InitialCount(wCountdownEvent* countdown);
WINPR_API BOOL CountdownEvent_IsSet(wCountdownEvent* countdown);
WINPR_API HANDLE CountdownEvent_WaitHandle(wCountdownEvent* countdown);
WINPR_API void CountdownEvent_AddCount(wCountdownEvent* countdown, DWORD signalCount);
WINPR_API BOOL CountdownEvent_Signal(wCountdownEvent* countdown, DWORD signalCount);
WINPR_API void CountdownEvent_Reset(wCountdownEvent* countdown, DWORD count);
WINPR_API wCountdownEvent* CountdownEvent_New(DWORD initialCount);
WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown);
/* Hash Table */
typedef UINT32 (*HASH_TABLE_HASH_FN)(const void* key);
typedef struct s_wHashTable wHashTable;
typedef BOOL (*HASH_TABLE_FOREACH_FN)(const void* key, void* value, void* arg);
WINPR_API size_t HashTable_Count(wHashTable* table);
#if defined(WITH_WINPR_DEPRECATED)
WINPR_API WINPR_DEPRECATED(int HashTable_Add(wHashTable* table, const void* key,
const void* value));
#endif
WINPR_API BOOL HashTable_Insert(wHashTable* table, const void* key, const void* value);
WINPR_API BOOL HashTable_Remove(wHashTable* table, const void* key);
WINPR_API void HashTable_Clear(wHashTable* table);
WINPR_API BOOL HashTable_Contains(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, const void* value);
WINPR_API void* HashTable_GetItemValue(wHashTable* table, const void* key);
WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, const void* key, const void* value);
WINPR_API size_t HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys);
WINPR_API BOOL HashTable_Foreach(wHashTable* table, HASH_TABLE_FOREACH_FN fn, VOID* arg);
WINPR_API UINT32 HashTable_PointerHash(const void* pointer);
WINPR_API BOOL HashTable_PointerCompare(const void* pointer1, const void* pointer2);
WINPR_API UINT32 HashTable_StringHash(const void* key);
WINPR_API BOOL HashTable_StringCompare(const void* string1, const void* string2);
WINPR_API void* HashTable_StringClone(const void* str);
WINPR_API void HashTable_StringFree(void* str);
WINPR_API wHashTable* HashTable_New(BOOL synchronized);
WINPR_API void HashTable_Free(wHashTable* table);
WINPR_API void HashTable_Lock(wHashTable* table);
WINPR_API void HashTable_Unlock(wHashTable* table);
WINPR_API wObject* HashTable_KeyObject(wHashTable* table);
WINPR_API wObject* HashTable_ValueObject(wHashTable* table);
WINPR_API BOOL HashTable_SetHashFunction(wHashTable* table, HASH_TABLE_HASH_FN fn);
/* Utility function to setup hash table for strings */
WINPR_API BOOL HashTable_SetupForStringData(wHashTable* table, BOOL stringValues);
/* BufferPool */
typedef struct s_wBufferPool wBufferPool;
WINPR_API SSIZE_T BufferPool_GetPoolSize(wBufferPool* pool);
WINPR_API SSIZE_T BufferPool_GetBufferSize(wBufferPool* pool, const void* buffer);
WINPR_API void* BufferPool_Take(wBufferPool* pool, SSIZE_T bufferSize);
WINPR_API BOOL BufferPool_Return(wBufferPool* pool, void* buffer);
WINPR_API void BufferPool_Clear(wBufferPool* pool);
WINPR_API wBufferPool* BufferPool_New(BOOL synchronized, SSIZE_T fixedSize, DWORD alignment);
WINPR_API void BufferPool_Free(wBufferPool* pool);
/* ObjectPool */
typedef struct s_wObjectPool wObjectPool;
WINPR_API void* ObjectPool_Take(wObjectPool* pool);
WINPR_API void ObjectPool_Return(wObjectPool* pool, void* obj);
WINPR_API void ObjectPool_Clear(wObjectPool* pool);
WINPR_API wObject* ObjectPool_Object(wObjectPool* pool);
WINPR_API wObjectPool* ObjectPool_New(BOOL synchronized);
WINPR_API void ObjectPool_Free(wObjectPool* pool);
/* Message Queue */
typedef struct s_wMessage wMessage;
typedef void (*MESSAGE_FREE_FN)(wMessage* message);
struct s_wMessage
{
UINT32 id;
void* context;
void* wParam;
void* lParam;
UINT64 time;
MESSAGE_FREE_FN Free;
};
typedef struct s_wMessageQueue wMessageQueue;
#define WMQ_QUIT 0xFFFFFFFF
WINPR_API wObject* MessageQueue_Object(wMessageQueue* queue);
WINPR_API HANDLE MessageQueue_Event(wMessageQueue* queue);
WINPR_API BOOL MessageQueue_Wait(wMessageQueue* queue);
WINPR_API size_t MessageQueue_Size(wMessageQueue* queue);
WINPR_API BOOL MessageQueue_Dispatch(wMessageQueue* queue, const wMessage* message);
WINPR_API BOOL MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam,
void* lParam);
WINPR_API BOOL MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
WINPR_API int MessageQueue_Get(wMessageQueue* queue, wMessage* message);
WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove);
/*! \brief Clears all elements in a message queue.
*
* \note If dynamically allocated data is part of the messages,
* a custom cleanup handler must be passed in the 'callback'
* argument for MessageQueue_New.
*
* \param queue The queue to clear.
*
* \return 0 in case of success or a error code otherwise.
*/
WINPR_API int MessageQueue_Clear(wMessageQueue* queue);
/*! \brief Creates a new message queue.
* If 'callback' is null, no custom cleanup will be done
* on message queue deallocation.
* If the 'callback' argument contains valid uninit or
* free functions those will be called by
* 'MessageQueue_Clear'.
*
* \param callback a pointer to custom initialization / cleanup functions.
* Can be NULL if not used.
*
* \return A pointer to a newly allocated MessageQueue or NULL.
*/
WINPR_API wMessageQueue* MessageQueue_New(const wObject* callback);
/*! \brief Frees resources allocated by a message queue.
* This function will only free resources allocated
* internally.
*
* \note Empty the queue before calling this function with
* 'MessageQueue_Clear', 'MessageQueue_Get' or
* 'MessageQueue_Peek' to free all resources allocated
* by the message contained.
*
* \param queue A pointer to the queue to be freed.
*/
WINPR_API void MessageQueue_Free(wMessageQueue* queue);
/* Message Pipe */
typedef struct
{
wMessageQueue* In;
wMessageQueue* Out;
} wMessagePipe;
WINPR_API void MessagePipe_PostQuit(wMessagePipe* pipe, int nExitCode);
WINPR_API wMessagePipe* MessagePipe_New(void);
WINPR_API void MessagePipe_Free(wMessagePipe* pipe);
/* Publisher/Subscriber Pattern */
typedef struct
{
DWORD Size;
const char* Sender;
} wEventArgs;
typedef void (*pEventHandler)(void* context, const wEventArgs* e);
#define MAX_EVENT_HANDLERS 32
typedef struct
{
const char* EventName;
wEventArgs EventArgs;
size_t EventHandlerCount;
pEventHandler EventHandlers[MAX_EVENT_HANDLERS];
} wEventType;
#define EventArgsInit(_event_args, _sender) \
memset(_event_args, 0, sizeof(*_event_args)); \
(_event_args)->e.Size = sizeof(*_event_args); \
(_event_args)->e.Sender = _sender
#define DEFINE_EVENT_HANDLER(name) \
typedef void (*p##name##EventHandler)(void* context, const name##EventArgs* e)
#define DEFINE_EVENT_RAISE(name) \
static INLINE int PubSub_On##name(wPubSub* pubSub, void* context, const name##EventArgs* e) \
{ \
WINPR_ASSERT(e); \
return PubSub_OnEvent(pubSub, #name, context, &e->e); \
}
#define DEFINE_EVENT_SUBSCRIBE(name) \
static INLINE int PubSub_Subscribe##name(wPubSub* pubSub, p##name##EventHandler EventHandler) \
{ \
return PubSub_Subscribe(pubSub, #name, (pEventHandler)EventHandler); \
}
#define DEFINE_EVENT_UNSUBSCRIBE(name) \
static INLINE int PubSub_Unsubscribe##name(wPubSub* pubSub, \
p##name##EventHandler EventHandler) \
{ \
return PubSub_Unsubscribe(pubSub, #name, (pEventHandler)EventHandler); \
}
#define DEFINE_EVENT_BEGIN(name) \
typedef struct \
{ \
wEventArgs e;
#define DEFINE_EVENT_END(name) \
} \
name##EventArgs; \
DEFINE_EVENT_HANDLER(name); \
DEFINE_EVENT_RAISE(name) \
DEFINE_EVENT_SUBSCRIBE(name) \
DEFINE_EVENT_UNSUBSCRIBE(name)
#define DEFINE_EVENT_ENTRY(name) \
{ \
#name, { sizeof(name##EventArgs), NULL }, 0, \
{ \
NULL \
} \
}
typedef struct s_wPubSub wPubSub;
WINPR_API void PubSub_Lock(wPubSub* pubSub);
WINPR_API void PubSub_Unlock(wPubSub* pubSub);
WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, size_t* count);
WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count);
WINPR_API wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName);
WINPR_API int PubSub_Subscribe(wPubSub* pubSub, const char* EventName,
pEventHandler EventHandler);
WINPR_API int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName,
pEventHandler EventHandler);
WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context,
const wEventArgs* e);
WINPR_API wPubSub* PubSub_New(BOOL synchronized);
WINPR_API void PubSub_Free(wPubSub* pubSub);
#ifdef __cplusplus
}
#endif
#endif /* WINPR_COLLECTIONS_H */