blob: 86b0727e60f71f78de996106d57e7ee5f696e9f7 [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* list.c
2 *
3 * This Module implements the List API
4 */
5
6/*****************************************************************************
7* Copyright (c) 2012-2020 by Rambus, Inc. and/or its subsidiaries.
8*
9* This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 2 of the License, or
12* any later version.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>.
21*****************************************************************************/
22
23/*----------------------------------------------------------------------------
24 * This module implements (provides) the following interface(s):
25 */
26
27// List API
28#include "list.h"
29
30
31/*----------------------------------------------------------------------------
32 * This module uses (requires) the following interface(s):
33 */
34
35// Default configuration
36#include "c_list.h"
37
38// Driver Framework Basic Definitions API
39#include "basic_defs.h"
40
41
42/*----------------------------------------------------------------------------
43 * Definitions and macros
44 */
45
46typedef struct
47{
48 // List head
49 List_Element_t * Head_p;
50
51 // List tail
52 List_Element_t * Tail_p;
53
54 // Number of elements in the list
55 unsigned int ElementCount;
56
57} List_t;
58
59/*----------------------------------------------------------------------------
60 * Local variables
61 */
62
63// Statically allocated list instances. This will be deprecated in future.
64static List_t List [LIST_MAX_NOF_INSTANCES];
65
66
67/*----------------------------------------------------------------------------
68 * List_Init
69 *
70 */
71List_Status_t
72List_Init(
73 const unsigned int ListID,
74 void * const ListInstance_p)
75{
76#ifdef LIST_STRICT_ARGS
77 if (ListID >= LIST_MAX_NOF_INSTANCES)
78 return LIST_ERROR_BAD_ARGUMENT;
79#endif // LIST_STRICT_ARGS
80
81 // Initialize the list instance
82 {
83 List_t * List_p;
84
85 if (ListInstance_p)
86 List_p = (List_t*)ListInstance_p;
87 else
88 List_p = &List[ListID];
89
90 List_p->ElementCount = 0;
91 List_p->Head_p = NULL;
92 List_p->Tail_p = NULL;
93 }
94
95 return LIST_STATUS_OK;
96}
97
98
99/*----------------------------------------------------------------------------
100 * List_Uninit
101 *
102 */
103List_Status_t
104List_Uninit(
105 const unsigned int ListID,
106 void * const ListInstance_p)
107{
108#ifdef LIST_STRICT_ARGS
109 if (ListID >= LIST_MAX_NOF_INSTANCES)
110 return LIST_ERROR_BAD_ARGUMENT;
111#endif // LIST_STRICT_ARGS
112
113 // Un-initialize the list instance
114 {
115 List_t * List_p;
116
117 if (ListInstance_p)
118 List_p = (List_t*)ListInstance_p;
119 else
120 List_p = &List[ListID];
121
122 List_p->ElementCount = 0;
123 List_p->Head_p = NULL;
124 List_p->Tail_p = NULL;
125 }
126
127 return LIST_STATUS_OK;
128}
129
130
131/*----------------------------------------------------------------------------
132 * List_AddToHead
133 *
134 */
135List_Status_t
136List_AddToHead(
137 const unsigned int ListID,
138 void * const ListInstance_p,
139 List_Element_t * const Element_p)
140{
141#ifdef LIST_STRICT_ARGS
142 if (ListID >= LIST_MAX_NOF_INSTANCES)
143 return LIST_ERROR_BAD_ARGUMENT;
144
145 if (Element_p == NULL)
146 return LIST_ERROR_BAD_ARGUMENT;
147#endif // LIST_STRICT_ARGS
148
149 // Add the element at the list head
150 {
151 List_Element_t * TempElement_p;
152 List_t * List_p;
153
154 if (ListInstance_p)
155 List_p = (List_t*)ListInstance_p;
156 else
157 List_p = &List[ListID];
158
159 TempElement_p = List_p->Head_p;
160 List_p->Head_p = Element_p;
161
162 // Previous element in the list, this is a head
163 Element_p->Internal[0] = NULL;
164
165 // Next element in the list
166 Element_p->Internal[1] = TempElement_p;
167
168 // Check if this is the first element
169 if (List_p->ElementCount == 0)
170 List_p->Tail_p = List_p->Head_p;
171 else
172 // Link the old head to the new head
173 TempElement_p->Internal[0] = Element_p;
174
175 List_p->ElementCount++;
176 }
177
178 return LIST_STATUS_OK;
179}
180
181
182/*----------------------------------------------------------------------------
183 * List_RemoveFromTail
184 *
185 */
186List_Status_t
187List_RemoveFromTail(
188 const unsigned int ListID,
189 void * const ListInstance_p,
190 List_Element_t ** const Element_pp)
191{
192#ifdef LIST_STRICT_ARGS
193 if (ListID >= LIST_MAX_NOF_INSTANCES)
194 return LIST_ERROR_BAD_ARGUMENT;
195
196 if (Element_pp == NULL)
197 return LIST_ERROR_BAD_ARGUMENT;
198
199#endif // LIST_STRICT_ARGS
200
201 // Remove the element from the list tail
202 {
203 List_Element_t * TempElement_p;
204 List_t * List_p;
205
206 if (ListInstance_p)
207 List_p = (List_t*)ListInstance_p;
208 else
209 List_p = &List[ListID];
210
211#ifdef LIST_STRICT_ARGS
212 if (List_p->ElementCount == 0)
213 return LIST_ERROR_BAD_ARGUMENT;
214#endif // LIST_STRICT_ARGS
215
216 // Get the previous for the tail element in the list
217 TempElement_p = (List_Element_t*)List_p->Tail_p->Internal[0];
218
219 List_p->Tail_p->Internal[0] = NULL;
220 List_p->Tail_p->Internal[1] = NULL;
221 *Element_pp = List_p->Tail_p;
222
223 // Set the new tail
224 List_p->Tail_p = TempElement_p;
225
226 // Check if this is the last element
227 if (List_p->ElementCount == 1)
228 List_p->Head_p = NULL;
229 else
230 // New tail must have no next element
231 List_p->Tail_p->Internal[1] = NULL;
232
233 List_p->ElementCount--;
234 }
235
236 return LIST_STATUS_OK;
237}
238
239
240/*----------------------------------------------------------------------------
241 * List_RemoveAnywhere
242 */
243List_Status_t
244List_RemoveAnywhere(
245 const unsigned int ListID,
246 void * const ListInstance_p,
247 List_Element_t * const Element_p)
248{
249#ifdef LIST_STRICT_ARGS
250 if (ListID >= LIST_MAX_NOF_INSTANCES)
251 return LIST_ERROR_BAD_ARGUMENT;
252
253 if (Element_p == NULL)
254 return LIST_ERROR_BAD_ARGUMENT;
255#endif // LIST_STRICT_ARGS
256
257 // Remove the element from the list tail
258 {
259 List_Element_t * PrevElement_p, * NextElement_p;
260 List_t * List_p;
261
262 if (ListInstance_p)
263 List_p = (List_t*)ListInstance_p;
264 else
265 List_p = &List[ListID];
266
267#ifdef LIST_STRICT_ARGS
268 if (List_p->ElementCount == 0)
269 return LIST_ERROR_BAD_ARGUMENT;
270
271 // Check element belongs to this list
272 {
273 unsigned int i;
274 List_Element_t * TempElement_p = List_p->Head_p;
275
276 for (i = 0; i < List_p->ElementCount; i++)
277 {
278 List_Element_t * p;
279
280 if (TempElement_p == Element_p)
281 break; // Found
282
283 p = TempElement_p->Internal[1];
284 if (p)
285 TempElement_p = p; // not end of list yet
286 else
287 return LIST_ERROR_BAD_ARGUMENT; // Not found
288 }
289
290 if (TempElement_p != Element_p)
291 return LIST_ERROR_BAD_ARGUMENT; // Not found
292 }
293#endif // LIST_STRICT_ARGS
294
295 PrevElement_p = Element_p->Internal[0];
296 NextElement_p = Element_p->Internal[1];
297
298 Element_p->Internal[0] = NULL;
299 Element_p->Internal[1] = NULL;
300
301 if (PrevElement_p)
302 PrevElement_p->Internal[1] = NextElement_p;
303 else
304 List_p->Head_p = NextElement_p;
305
306 if (NextElement_p)
307 NextElement_p->Internal[0] = PrevElement_p;
308 else
309 List_p->Tail_p = PrevElement_p;
310
311 List_p->ElementCount--;
312 }
313
314 return LIST_STATUS_OK;
315}
316
317
318/*----------------------------------------------------------------------------
319 * List_GetListElementCount
320 *
321 */
322List_Status_t
323List_GetListElementCount(
324 const unsigned int ListID,
325 void * const ListInstance_p,
326 unsigned int * const Count_p)
327{
328#ifdef LIST_STRICT_ARGS
329 if (ListID >= LIST_MAX_NOF_INSTANCES)
330 return LIST_ERROR_BAD_ARGUMENT;
331
332 if (Count_p == NULL)
333 return LIST_ERROR_BAD_ARGUMENT;
334#endif // LIST_STRICT_ARGS
335
336 {
337 List_t * List_p;
338
339 if (ListInstance_p)
340 List_p = (List_t*)ListInstance_p;
341 else
342 List_p = &List[ListID];
343
344 *Count_p = List_p->ElementCount;
345 }
346
347 return LIST_STATUS_OK;
348}
349
350
351#ifdef LIST_FULL_API
352/*----------------------------------------------------------------------------
353 * List_RemoveFromHead
354 *
355 */
356List_Status_t
357List_RemoveFromHead(
358 const unsigned int ListID,
359 void * const ListInstance_p,
360 List_Element_t ** const Element_pp)
361{
362 List_t * List_p;
363
364 if (ListInstance_p)
365 List_p = (List_t*)ListInstance_p;
366 else
367 List_p = &List[ListID];
368
369#ifdef LIST_STRICT_ARGS
370 if (ListID >= LIST_MAX_NOF_INSTANCES)
371 return LIST_ERROR_BAD_ARGUMENT;
372
373 if (Element_pp == NULL)
374 return LIST_ERROR_BAD_ARGUMENT;
375
376 if (List_p->ElementCount == 0)
377 return LIST_ERROR_BAD_ARGUMENT;
378#endif // LIST_STRICT_ARGS
379
380 // Remove the element from the list head
381 {
382 List_Element_t * TempElement_p;
383
384 // Get the next for the head element in the list
385 TempElement_p = (List_Element_t*)List_p->Head_p->Internal[1];
386
387 List_p->Head_p->Internal[0] = NULL;
388 List_p->Head_p->Internal[1] = NULL;
389 *Element_pp = List_p->Head_p;
390
391 List_p->Head_p = TempElement_p;
392
393 // Check if this is the last element
394 if (List_p->ElementCount == 1)
395 List_p->Tail_p = NULL;
396 else
397 List_p->Head_p->Internal[0] = NULL;
398
399 List_p->ElementCount--;
400 }
401
402 return LIST_STATUS_OK;
403}
404
405
406/*----------------------------------------------------------------------------
407 * List_GetHead
408 */
409List_Status_t
410List_GetHead(
411 const unsigned int ListID,
412 void * const ListInstance_p,
413 const List_Element_t ** const Element_pp)
414{
415#ifdef LIST_STRICT_ARGS
416 if (ListID >= LIST_MAX_NOF_INSTANCES)
417 return LIST_ERROR_BAD_ARGUMENT;
418
419 if (Element_pp == NULL)
420 return LIST_ERROR_BAD_ARGUMENT;
421#endif // LIST_STRICT_ARGS
422
423 // Get the list head
424 {
425 List_t * List_p;
426
427 if (ListInstance_p)
428 List_p = (List_t*)ListInstance_p;
429 else
430 List_p = &List[ListID];
431
432 *Element_pp = List_p->Head_p;
433 }
434
435 return LIST_STATUS_OK;
436}
437#endif // LIST_FULL_API
438
439
440/*----------------------------------------------------------------------------
441 * List_GetInstanceByteCount
442 *
443 * Gets the memory size of the list instance (in bytes) excluding the list
444 * elements memory size. This list memory size can be used to allocate a list
445 * instance and pass a pointer to it subsequently to the List_*() functions.
446 *
447 * This function is re-entrant and can be called any time.
448 *
449 * Return Values
450 * Size of the list administration memory in bytes.
451 */
452unsigned int
453List_GetInstanceByteCount(void)
454{
455 return sizeof(List_t);
456}
457
458
459/* end of file list.c */