MediaProcessors
llist.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, 2018 Rafael Antoniello
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
35 #include "llist.h"
36 
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include "check_utils.h"
41 #include "log.h"
42 #include "stat_codes.h"
43 
44 /* **** Definitions **** */
45 
46 /* **** Prototypes **** */
47 
48 /* **** Implementations **** */
49 
50 /*
51  * Notes:
52  * Is understood that new data is always pushed as the first element;
53  * If the list is not yet initialized (namely, is "empty"), the push
54  * operation works as well as initializer as long 'ref_llist_head' is set
55  * originally to NULL.
56  */
57 int llist_push(llist_t** ref_llist_head, void *data)
58 {
59  llist_t *new_node;
60  LOG_CTX_INIT(NULL);
61 
62  /* Check arguments */
63  CHECK_DO(ref_llist_head!= NULL, return STAT_EINVAL);
64  CHECK_DO(data!= NULL, return STAT_EINVAL);
65 
66  new_node= (llist_t*)malloc(sizeof(llist_t));
67  CHECK_DO(new_node!= NULL, return STAT_ENOMEM);
68 
69  new_node->data= data;
70  new_node->next= *ref_llist_head;
71  *ref_llist_head= new_node;
72  return STAT_SUCCESS;
73 }
74 
75 void* llist_pop(llist_t** ref_llist_head)
76 {
77  llist_t *head;
78  void *data;
79  LOG_CTX_INIT(NULL);
80 
81  /* Check arguments */
82  CHECK_DO(ref_llist_head!= NULL, return NULL);
83 
84  /* If list is empty we are done */
85  if((head= *ref_llist_head)== NULL)
86  return NULL;
87 
88  data= head->data; // get data
89  *ref_llist_head= head->next; // update head (unlink popped node)
90  free(head);
91 
92  return data;
93 }
94 
95 int llist_len(const llist_t *llist_head)
96 {
97  int cnt= 0;
98  llist_t *curr_node;
99  //LOG_CTX_INIT(NULL);
100 
101  /* Check arguments.
102  * Note: argument 'llist_head' is allowed to be NULL.
103  */
104 
105  curr_node= (llist_t*)llist_head;
106  while(curr_node!= NULL) {
107  cnt++;
108  curr_node= curr_node->next;
109  }
110  return cnt;
111 }
112 
113 void* llist_get_nth(const llist_t *llist_head, int index)
114 {
115  int cnt= 0;
116  llist_t *curr_node;
117  LOG_CTX_INIT(NULL);
118 
119  /* Check arguments.
120  * Note: argument 'llist_head' is allowed to be NULL.
121  */
122  if(llist_head== NULL)
123  return NULL; // element not found (empty list)
124  CHECK_DO(index>= 0, return NULL);
125 
126  curr_node= (llist_t*)llist_head;
127 
128  // the index of the node we're currently looking at
129  while(curr_node!= NULL) {
130  if(cnt++== index)
131  return curr_node->data;
132  curr_node= curr_node->next;
133  }
134  return NULL; // element not found
135 }
136 
137 int llist_insert_nth(llist_t **ref_llist_head, int index, void *data)
138 {
139  llist_t **curr_node;
140  int i;
141  LOG_CTX_INIT(NULL);
142 
143  /* Check arguments */
144  CHECK_DO(ref_llist_head!= NULL, return STAT_ERROR);
145  CHECK_DO(index>= 0, return STAT_ERROR);
146  CHECK_DO(data!= NULL, return STAT_ERROR);
147 
148  if(index== 0) // Position 0 is a special case
149  return llist_push(ref_llist_head, data);
150 
151  /* Find node at given index */
152  curr_node= ref_llist_head;
153  for(i= 0; i< index- 1; i++) {
154  if(*curr_node== NULL) // index was too big
155  return llist_push(curr_node, data); // Append at the end
156  curr_node= &(*curr_node)->next;
157  }
158  if(*curr_node== NULL) // index was too big
159  return llist_push(curr_node, data); // Append at the end
160 
161  /* Push new node at given index */
162  return llist_push(&(*curr_node)->next, data);
163 }
void * llist_get_nth(const llist_t *llist_head, int index)
Definition: llist.c:113
Definition: llist.h:49
int llist_insert_nth(llist_t **ref_llist_head, int index, void *data)
Definition: llist.c:137
General status codes enumeration.
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
int llist_push(llist_t **ref_llist_head, void *data)
Definition: llist.c:57
Simple linked-list utility implementation.
int llist_len(const llist_t *llist_head)
Definition: llist.c:95
void * llist_pop(llist_t **ref_llist_head)
Definition: llist.c:75