DVBCore  20.3.0
DVBCore Documentation
stbllist.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 //---includes for this file----------------------------------------------------
26 // compiler library header files
27 
28 #include <stdlib.h>
29 
30 // third party header files
31 
32 // Ocean Blue Software header files
33 
34 #include <techtype.h>
35 #include <dbgfuncs.h>
36 
37 #include "stbllist.h"
38 #include "stbheap.h"
39 
40 
41 //---constant definitions for this file----------------------------------------
42 
43 //---local typedef structs for this file---------------------------------------
44 
45 //---local (static) variable declarations for this file------------------------
46 // (internal variables declared static to make them local)
47 
48 //---local function prototypes for this file-----------------------------------
49 // (internal functions declared static to make them local)
50 
51 static void InsertBlkInList(LINK_LIST_PTR_BLK *prev_blk, LINK_LIST_PTR_BLK *new_blk,
52  LINK_LIST_PTR_BLK *next_blk, LINK_LIST_PTR_BLK **prev_blk_next_ptr,
53  LINK_LIST_PTR_BLK **next_blk_prev_ptr);
54 
55 static void quick_sort(void *blocks_array, size_t num_blocks, size_t block_size, short int (*cmp_func)(const void *, const void *));
56 static void rec_quick_sort(void *blocks_array[], U16BIT left, U16BIT right, short int (*cmp_func)(const void *, const void *));
57 
58 //---local function definitions------------------------------------------------
59 
83 static void InsertBlkInList(LINK_LIST_PTR_BLK *prev_blk,
84  LINK_LIST_PTR_BLK *new_blk,
85  LINK_LIST_PTR_BLK *next_blk,
86  LINK_LIST_PTR_BLK **prev_blk_next_ptr,
87  LINK_LIST_PTR_BLK **next_blk_prev_ptr)
88 {
89 // FUNCTION_START(InsertBlkInList);
90 
91  // make new blk point forward to next blk and back to prev blk
92  new_blk->next = next_blk;
93  new_blk->prev = prev_blk;
94 
95  // make prev blk point forward to new blk
96  *prev_blk_next_ptr = new_blk;
97 
98  // make next blk point backwards to new blk
99  *next_blk_prev_ptr = new_blk;
100 
101 // FUNCTION_FINISH(InsertBlkInList);
102 }
103 
104 //---global function definitions-----------------------------------------------
120 {
121 // FUNCTION_START(STB_LLInitialiseHeader);
122 
123  hdr->null_next = NULL;
124  hdr->first = hdr;
125  hdr->last = hdr;
126 
127 // FUNCTION_FINISH(STB_LLInitialiseHeader);
128 }
129 
161 BOOLEAN STB_LLSort(LINK_LIST_HEADER *ll_hdr, S16BIT (*cmp_func)(LINK_LIST_PTR_BLK **, LINK_LIST_PTR_BLK **))
162 {
163  LINK_LIST_PTR_BLK **blocks_array; //ptr to a buffer of LINK_LIST_PTR_BLK ptrs
164  LINK_LIST_PTR_BLK *ll_block;
165  U32BIT num_blocks;
166  U32BIT block_size;
167  U16BIT i;
168  BOOLEAN success;
169 
170 // FUNCTION_START(STB_LLSort);
171 
172  ASSERT(cmp_func != NULL);
173  ASSERT(ll_hdr != NULL);
174 
175  success = TRUE;
176 
177  num_blocks = STB_LLGetNumBlocks(ll_hdr);
178 
179  if (num_blocks > 1)
180  {
181  blocks_array = (LINK_LIST_PTR_BLK **)STB_GetMemory(num_blocks * sizeof(LINK_LIST_PTR_BLK *));
182 
183  if (blocks_array == NULL)
184  {
185  success = FALSE;
186  }
187  else
188  {
189  // copy linked list block pointers from database to block array
190  ll_block = STB_LLGetFirstBlock(ll_hdr);
191  for (i = 0; i < num_blocks; i++)
192  {
193  ASSERT(ll_block != NULL);
194  blocks_array[i] = ll_block;
195  if (ll_block)
196  {
197  ll_block = STB_LLGetNextBlock(ll_block);
198  }
199  }
200 
201  ASSERT(ll_block == NULL);
202 
203  ASSERT(sizeof(size_t) == sizeof(U32BIT));
204 
205  block_size = sizeof(LINK_LIST_PTR_BLK *);
206  // run qsort on block array
207  // cast is used here to match required format of qsort
208 
209  // "quick sort" function to sort unicode name strings
210  quick_sort((void *)blocks_array, (size_t)num_blocks, (size_t)block_size, (short int (*)(const void *, const void *))cmp_func);
211 
212  // restore sorted array of block pointers to database linked list
213  for (i = 0; i < num_blocks; i++) //move each item in the array to last position in the linked list
214  {
215  STB_LLRemoveBlock(blocks_array[i]);
216  STB_LLAddBlockToEnd(ll_hdr, blocks_array[i]);
217  }
218 
219  STB_FreeMemory(blocks_array);
220  }
221  }
222 
223 // FUNCTION_FINISH(STB_LLSort);
224  return success;
225 }
226 
241 static void quick_sort(void *blocks_array, size_t num_blocks, size_t block_size, short int (*cmp_func)(const void *, const void *))
242 {
243 // FUNCTION_START(quick_sort);
244  USE_UNWANTED_PARAM(block_size);
245 
246  // cast as (void**) to allow dereferencing as void* in array form:
247  rec_quick_sort((void **)blocks_array, 0, (U16BIT)(num_blocks - 1), cmp_func);
248 
249 // FUNCTION_FINISH(quick_sort);
250 }
251 
267 static void rec_quick_sort(void *blocks_array[], U16BIT left, U16BIT right, short int (*cmp_func)(const void *, const void *))
268 {
269  register U16BIT i, j;
270  void *temp;
271 
272 
273 // FUNCTION_START(rec_quick_sort);
274 
275  while (right > left)
276  {
277  i = left;
278  j = right;
279  temp = blocks_array[left];
280 
281  // split array in two
282  while (i < j)
283  {
284  for (; ((j > left) && (cmp_func(&blocks_array[j], &temp) > 0)); j--)
285  ;
286 
287  for (blocks_array[i] = blocks_array[j]; ((i < j) && cmp_func(&blocks_array[i], &temp) <= 0); i++)
288  ;
289  // swap items
290  blocks_array[j] = blocks_array[i];
291  }
292  blocks_array[i] = temp;
293 
294  // sort recursively, the smallest first
295  if ((i - left) < (right - i))
296  {
297  rec_quick_sort(blocks_array, left, (U16BIT)i, cmp_func);
298  left = i + 1;
299  }
300  else
301  {
302  rec_quick_sort(blocks_array, (U16BIT)(i + 1), right, cmp_func);
303  right = i - 1;
304  }
305  }
306 
307 // FUNCTION_FINISH(rec_quick_sort);
308 }
309 
310 /*---------------------------------------------*/
311 
326 {
327  LINK_LIST_PTR_BLK *prev_blk;
328  LINK_LIST_PTR_BLK **prev_blk_next_ptr;
329 
330 // FUNCTION_START(STB_LLAddBlockToEnd);
331 
332  ASSERT(hdr != NULL);
333  ASSERT(new_blk != NULL);
334 
335  // get pointer to the last block in the list - this becomes the previous block to new_blk
336  prev_blk = hdr->last;
337 
338  // check if prev_blk is the header - if so there are no entries in the list yet and
339  // prev_blk_next_ptr must point to hdr->first. Otherwise it points to prev_blk->next
340  if (prev_blk->next == NULL)
341  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(hdr->first);
342  else
343  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(prev_blk->next);
344 
345  // add new_blk between prev_blk and hdr
346  InsertBlkInList(prev_blk, new_blk, (LINK_LIST_PTR_BLK *)hdr, prev_blk_next_ptr, (LINK_LIST_PTR_BLK **)&(hdr->last));
347 
348 // FUNCTION_FINISH(STB_LLAddBlockToEnd);
349 }
350 
365 {
366  LINK_LIST_PTR_BLK *next_blk;
367  LINK_LIST_PTR_BLK **next_blk_prev_ptr;
368 
369 // FUNCTION_START(STB_LLAddBlockToStart);
370 
371  ASSERT(hdr != NULL);
372  ASSERT(new_blk != NULL);
373 
374  // get pointer to the next block in the list - this becomes the next block to new_blk
375  next_blk = hdr->first;
376 
377  // check if next_blk is the header - if so there are no entries in the list yet and
378  // next_blk_prev_ptr must point to hdr->prev. Otherwise it points to next_blk->prev
379  if (next_blk->next == NULL)
380  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(hdr->last);
381  else
382  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(next_blk->prev);
383 
384  // add new_blk between hdr and next_blk
385  InsertBlkInList((LINK_LIST_PTR_BLK *)hdr, new_blk, next_blk, (LINK_LIST_PTR_BLK **)&(hdr->first), next_blk_prev_ptr);
386 
387 // FUNCTION_FINISH(STB_LLAddBlockToStart);
388 }
389 
404 {
405  LINK_LIST_PTR_BLK *prev_blk;
406  LINK_LIST_PTR_BLK **prev_blk_next_ptr;
407 
408 // FUNCTION_START(STB_LLAddBlockBefore);
409 
410  ASSERT(next_blk != NULL);
411  ASSERT(new_blk != NULL);
412 
413  // get pointer to the previous block from next_blk - this block will become the one previous
414  // to new_blk
415  prev_blk = next_blk->prev;
416 
417  // if prev_blk's next ptr is NULL then it is the list header - we must therefore be at the start
418  // of the list. Set prev_blk_next_ptr accordingly.
419  if (prev_blk->next == NULL)
420  {
421  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(((LINK_LIST_HEADER *)prev_blk)->first);
422  }
423  else
424  {
425  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(prev_blk->next);
426  }
427 
428  // add new_blk between prev_blk and next_blk
429  InsertBlkInList(prev_blk, new_blk, next_blk, prev_blk_next_ptr, (LINK_LIST_PTR_BLK **)&(next_blk->prev));
430 
431 // FUNCTION_FINISH(STB_LLAddBlockBefore);
432 }
433 
448 {
449  LINK_LIST_PTR_BLK *next_blk;
450  LINK_LIST_PTR_BLK **next_blk_prev_ptr;
451 
452 // FUNCTION_START(STB_LLAddBlockAfter);
453 
454  ASSERT(prev_blk != NULL);
455  ASSERT(new_blk != NULL);
456 
457  // get pointer to the next block from prev_blk - this block will become the one after new_blk
458  next_blk = prev_blk->next;
459 
460  // if next_blk's next ptr is NULL then it is the list header - we must therefore be at the end
461  // of the list. Set next_blk_prev_ptr accordingly
462  if (next_blk->next == NULL)
463  {
464  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(((LINK_LIST_HEADER *)next_blk)->last);
465  }
466  else
467  {
468  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(next_blk->prev);
469  }
470 
471  // add new_blk between prev_blk and next_blk
472  InsertBlkInList(prev_blk, new_blk, next_blk, (LINK_LIST_PTR_BLK **)&(prev_blk->next), next_blk_prev_ptr);
473 
474 // FUNCTION_FINISH(STB_LLAddBlockAfter);
475 }
476 
489 {
490  LINK_LIST_PTR_BLK *prev_blk;
491  LINK_LIST_PTR_BLK **prev_blk_next_ptr;
492  LINK_LIST_PTR_BLK *next_blk;
493  LINK_LIST_PTR_BLK **next_blk_prev_ptr;
494 
495 // FUNCTION_START(STB_LLRemoveBlock);
496 
497  ASSERT(blk != NULL);
498 
499  // get pointer to the previous block to blk.
500  prev_blk = blk->prev;
501  if (prev_blk != NULL)
502  {
503  // if prev_blk's next ptr is NULL then it is the list header - we must therefore be at the start
504  // of the list. Set prev_blk_next_ptr accordingly.
505  if (prev_blk->next == NULL)
506  {
507  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(((LINK_LIST_HEADER *)prev_blk)->first);
508  }
509  else
510  {
511  prev_blk_next_ptr = (LINK_LIST_PTR_BLK **)&(prev_blk->next);
512  }
513  }
514  else
515  {
516  prev_blk_next_ptr = NULL;
517  }
518 
519  // get pointer to the next block to blk
520  next_blk = blk->next;
521  if (next_blk != NULL)
522  {
523  // if next_blk's next ptr is NULL then it is the list header - we must therefore be at the end
524  // of the list. Set next_blk_prev_ptr accordingly
525  if (next_blk->next == NULL)
526  {
527  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(((LINK_LIST_HEADER *)next_blk)->last);
528  }
529  else
530  {
531  next_blk_prev_ptr = (LINK_LIST_PTR_BLK **)&(next_blk->prev);
532  }
533  }
534  else
535  {
536  next_blk_prev_ptr = NULL;
537  }
538 
539  if (prev_blk_next_ptr != NULL)
540  {
541  // set prev_blk_next_ptr to point at next_blk
542  *prev_blk_next_ptr = next_blk;
543  }
544 
545  if (next_blk_prev_ptr != NULL)
546  {
547  // set next_blk_prev_ptr to point at prev_blk
548  *next_blk_prev_ptr = prev_blk;
549  }
550 
551 // FUNCTION_FINISH(STB_LLRemoveBlock);
552 }
553 
567 {
568  LINK_LIST_PTR_BLK *next_blk;
569 
570 // FUNCTION_START(STB_LLGetNextBlock);
571 
572  ASSERT(blk != NULL);
573 
574  // get pointer to next block
575  next_blk = blk->next;
576 
577  // check if next_blk is the header (next pointer will be NULL). If it is the header then we are
578  // at the end of the list so set next_blk to NULL.
579  if (next_blk->next == NULL)
580  next_blk = NULL;
581 
582 // FUNCTION_FINISH(STB_LLGetNextBlock);
583 
584  // return next_blk
585  return(next_blk);
586 }
587 
601 {
602  LINK_LIST_PTR_BLK *prev_blk;
603 
604 // FUNCTION_START(STB_LLGetPrevBlock);
605 
606  ASSERT(blk != NULL);
607 
608  // get pointer to prev block
609  prev_blk = blk->prev;
610 
611  // check if prev_blk is the header (next pointer will be NULL). If it is the header then we are
612  // at the start of the list so set prev_blk to NULL.
613  if (prev_blk->next == NULL)
614  prev_blk = NULL;
615 
616 // FUNCTION_FINISH(STB_LLGetPrevBlock);
617 
618  // return prev_blk
619  return(prev_blk);
620 }
621 
634 {
635  LINK_LIST_PTR_BLK *next_blk;
636 
637 // FUNCTION_START(STB_LLGetFirstBlock);
638 
639  ASSERT(hdr != NULL);
640 
641  // get pointer to the next block
642  next_blk = hdr->first;
643 
644  // if next_blk is pointing to the header then the list is empty - set next_blk to null
645  if (next_blk->next == NULL)
646  next_blk = NULL;
647 
648 // FUNCTION_FINISH(STB_LLGetFirstBlock);
649 
650  // return next_blk pointer
651  return(next_blk);
652 }
653 
666 {
667  LINK_LIST_PTR_BLK *prev_blk;
668 
669 // FUNCTION_START(STB_LLGetLastBlock);
670 
671  ASSERT(hdr != NULL);
672 
673  // get pointer to the previous block
674  prev_blk = hdr->last;
675 
676  // if prev_blk is pointing to the header itself then the list is empty - set prev_blk to null
677  if (prev_blk->next == NULL)
678  prev_blk = NULL;
679 
680 // FUNCTION_FINISH(STB_LLGetLastBlock);
681 
682  // return prev_blk pointer
683  return(prev_blk);
684 }
685 
699 {
700  LINK_LIST_PTR_BLK *next_blk;
701  U16BIT i;
702 
703 // FUNCTION_START(STB_LLGetBlock);
704 
705  ASSERT(hdr != NULL);
706 
707  // get pointer to the first_block
708  next_blk = STB_LLGetFirstBlock(hdr);
709  i = 0;
710 
711  // count blocks along list until we reach the number required
712  while ((next_blk != NULL) && (i < num))
713  {
714  next_blk = STB_LLGetNextBlock(next_blk);
715  i++;
716  }
717 
718 // FUNCTION_FINISH(STB_LLGetBlock);
719 
720  // return pointer found - it may be null
721  return(next_blk);
722 }
723 
737 {
738  LINK_LIST_PTR_BLK *next_blk;
739  U16BIT i;
740 
741 // FUNCTION_START(STB_LLGetNumBlocks);
742 
743  ASSERT(hdr != NULL);
744 
745  // get pointer to the first_block
746  next_blk = STB_LLGetFirstBlock(hdr);
747  i = 0;
748 
749  // step along list counting blocks
750  while (next_blk != NULL)
751  {
752  i++;
753  next_blk = STB_LLGetNextBlock(next_blk);
754  }
755 
756 // FUNCTION_FINISH(STB_LLGetNumBlocks);
757 
758  // return the count
759  return(i);
760 }
761 
775 {
776  LINK_LIST_PTR_BLK *next_blk;
777 
778 // FUNCTION_START(STB_LLCheckBlockInList);
779 
780  ASSERT(hdr != NULL);
781  ASSERT(blk != NULL);
782 
783  // get pointer to the first_block
784  next_blk = STB_LLGetFirstBlock(hdr);
785 
786  // step along list looking for specified block
787  while (next_blk != NULL)
788  {
789  // if next_blk == blk then found block so return TRUE
790  if (next_blk == blk)
791  return(TRUE);
792 
793  // move on to next block in list
794 
795 
796  next_blk = STB_LLGetNextBlock(next_blk);
797  }
798 
799 // FUNCTION_FINISH(STB_LLCheckBlockInList);
800 
801  // not found so return false
802  return(FALSE);
803 }
804 
805 //*****************************************************************************
806 // End of file
807 //*****************************************************************************
808 
809 
U16BIT STB_LLGetNumBlocks(LINK_LIST_HEADER *hdr)
Counts and returns the number of blocks in a linked list.
Definition: stbllist.c:736
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
BOOLEAN STB_LLCheckBlockInList(LINK_LIST_HEADER *hdr, LINK_LIST_PTR_BLK *blk)
Checks if the supplied pointer is to a block in the specified list.
Definition: stbllist.c:774
void STB_LLRemoveBlock(LINK_LIST_PTR_BLK *blk)
Removes the block identified by the blk pointer from its linked list.
Definition: stbllist.c:488
LINK_LIST_PTR_BLK * STB_LLGetLastBlock(LINK_LIST_HEADER *hdr)
Returns a pointer to the last block in the linked list, identified by hdr.
Definition: stbllist.c:665
void STB_LLAddBlockBefore(LINK_LIST_PTR_BLK *next_blk, LINK_LIST_PTR_BLK *new_blk)
Adds the block identified by the new_blk pointer to the linked list before the block identified by th...
Definition: stbllist.c:403
void STB_LLAddBlockToEnd(LINK_LIST_HEADER *hdr, LINK_LIST_PTR_BLK *new_blk)
Adds the block identified by the new_blk pointer to the end of the linked list identified by the list...
Definition: stbllist.c:325
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
void STB_LLInitialiseHeader(LINK_LIST_HEADER *hdr)
Initialise the header variables of the linked list.
Definition: stbllist.c:119
Debug functions header file.
Header file - Function prototypes for linked lists.
System Wide Global Technical Data Type Definitions.
void STB_LLAddBlockToStart(LINK_LIST_HEADER *hdr, LINK_LIST_PTR_BLK *new_blk)
Adds the block identified by the new_blk pointer to the start of the linked list identified by the li...
Definition: stbllist.c:364
BOOLEAN STB_LLSort(LINK_LIST_HEADER *ll_hdr, S16BIT(*cmp_func)(LINK_LIST_PTR_BLK **, LINK_LIST_PTR_BLK **))
Sorts the blocks of a link list object in ascending or descending order NOTE: The order in which the ...
Definition: stbllist.c:161
Header file - Function prototypes for heap memory.
LINK_LIST_PTR_BLK * STB_LLGetFirstBlock(LINK_LIST_HEADER *hdr)
Returns a pointer to the first block in the linked list, identified by hdr.
Definition: stbllist.c:633
void STB_LLAddBlockAfter(LINK_LIST_PTR_BLK *prev_blk, LINK_LIST_PTR_BLK *new_blk)
Adds the block identified by the new_blk pointer to the linked list after the block identified by the...
Definition: stbllist.c:447
LINK_LIST_PTR_BLK * STB_LLGetPrevBlock(LINK_LIST_PTR_BLK *blk)
Returns a pointer to the previous block in the linked list, or NULL if at the start of the list...
Definition: stbllist.c:600
LINK_LIST_PTR_BLK * STB_LLGetBlock(LINK_LIST_HEADER *hdr, U16BIT num)
Returns a pointer to the n-th block in the list.
Definition: stbllist.c:698
LINK_LIST_PTR_BLK * STB_LLGetNextBlock(LINK_LIST_PTR_BLK *blk)
Returns a pointer to the next block in the linked list, or NULL if at the end of the list...
Definition: stbllist.c:566