[SETUPLIB][USETUP] Introduce a 'SetupLib' library. CORE-13544
[reactos.git] / base / setup / lib / genlist.c
1 /*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Generic list functions
5 * COPYRIGHT: Copyright 2004-2018 Eric Kohl
6 * Copyright 2008-2018 Christoph von Wittich <christoph at reactos.org>
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "precomp.h"
12
13 #include "genlist.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* FUNCTIONS ****************************************************************/
19
20 PGENERIC_LIST
21 CreateGenericList(VOID)
22 {
23 PGENERIC_LIST List;
24
25 List = (PGENERIC_LIST)RtlAllocateHeap(ProcessHeap,
26 0,
27 sizeof(GENERIC_LIST));
28 if (List == NULL)
29 return NULL;
30
31 InitializeListHead(&List->ListHead);
32 List->NumOfEntries = 0;
33
34 List->CurrentEntry = NULL;
35 List->BackupEntry = NULL;
36
37 return List;
38 }
39
40 VOID
41 DestroyGenericList(
42 IN OUT PGENERIC_LIST List,
43 IN BOOLEAN FreeUserData)
44 {
45 PGENERIC_LIST_ENTRY ListEntry;
46 PLIST_ENTRY Entry;
47
48 /* Release list entries */
49 while (!IsListEmpty(&List->ListHead))
50 {
51 Entry = RemoveHeadList(&List->ListHead);
52 ListEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
53
54 /* Release user data */
55 if (FreeUserData && ListEntry->UserData != NULL)
56 RtlFreeHeap(ProcessHeap, 0, ListEntry->UserData);
57
58 /* Release list entry */
59 RtlFreeHeap(ProcessHeap, 0, ListEntry);
60 }
61
62 /* Release list head */
63 RtlFreeHeap(ProcessHeap, 0, List);
64 }
65
66 BOOLEAN
67 AppendGenericListEntry(
68 IN OUT PGENERIC_LIST List,
69 IN PCHAR Text,
70 IN PVOID UserData,
71 IN BOOLEAN Current)
72 {
73 PGENERIC_LIST_ENTRY Entry;
74
75 Entry = (PGENERIC_LIST_ENTRY)RtlAllocateHeap(ProcessHeap,
76 0,
77 sizeof(GENERIC_LIST_ENTRY) + strlen(Text));
78 if (Entry == NULL)
79 return FALSE;
80
81 strcpy (Entry->Text, Text);
82 Entry->List = List;
83 Entry->UserData = UserData;
84
85 InsertTailList(&List->ListHead, &Entry->Entry);
86 List->NumOfEntries++;
87
88 if (Current || List->CurrentEntry == NULL)
89 {
90 List->CurrentEntry = Entry;
91 }
92
93 return TRUE;
94 }
95
96 VOID
97 SetCurrentListEntry(
98 IN PGENERIC_LIST List,
99 IN PGENERIC_LIST_ENTRY Entry)
100 {
101 if (Entry->List != List)
102 return;
103 List->CurrentEntry = Entry;
104 }
105
106 PGENERIC_LIST_ENTRY
107 GetCurrentListEntry(
108 IN PGENERIC_LIST List)
109 {
110 return List->CurrentEntry;
111 }
112
113 PGENERIC_LIST_ENTRY
114 GetFirstListEntry(
115 IN PGENERIC_LIST List)
116 {
117 PLIST_ENTRY Entry = List->ListHead.Flink;
118
119 if (Entry == &List->ListHead)
120 return NULL;
121 return CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
122 }
123
124 PGENERIC_LIST_ENTRY
125 GetNextListEntry(
126 IN PGENERIC_LIST_ENTRY Entry)
127 {
128 PLIST_ENTRY Next = Entry->Entry.Flink;
129
130 if (Next == &Entry->List->ListHead)
131 return NULL;
132 return CONTAINING_RECORD(Next, GENERIC_LIST_ENTRY, Entry);
133 }
134
135 PVOID
136 GetListEntryUserData(
137 IN PGENERIC_LIST_ENTRY Entry)
138 {
139 return Entry->UserData;
140 }
141
142 LPCSTR
143 GetListEntryText(
144 IN PGENERIC_LIST_ENTRY Entry)
145 {
146 return Entry->Text;
147 }
148
149 ULONG
150 GetNumberOfListEntries(
151 IN PGENERIC_LIST List)
152 {
153 return List->NumOfEntries;
154 }
155
156 VOID
157 SaveGenericListState(
158 IN PGENERIC_LIST List)
159 {
160 List->BackupEntry = List->CurrentEntry;
161 }
162
163 VOID
164 RestoreGenericListState(
165 IN PGENERIC_LIST List)
166 {
167 List->CurrentEntry = List->BackupEntry;
168 }
169
170 BOOLEAN
171 GenericListHasSingleEntry(
172 IN PGENERIC_LIST List)
173 {
174 if (!IsListEmpty(&List->ListHead) && List->ListHead.Flink == List->ListHead.Blink)
175 return TRUE;
176
177 /* if both list head pointers (which normally point to the first and last list member, respectively)
178 point to the same entry then it means that there's just a single thing in there, otherwise... false! */
179 return FALSE;
180 }
181
182 /* EOF */