Merge lp:~stefan.goetz-deactivatedaccount/hipl/hip-ll-extensions into lp:hipl

Proposed by Stefan Götz
Status: Rejected
Rejected by: Stefan Götz
Proposed branch: lp:~stefan.goetz-deactivatedaccount/hipl/hip-ll-extensions
Merge into: lp:hipl
Diff against target: 973 lines (+438/-210)
12 files modified
Makefile.am (+1/-0)
hipd/hip_socket.c (+5/-5)
hipd/maintenance.c (+2/-2)
hipd/pkt_handling.c (+2/-2)
hipd/registration.c (+9/-9)
hipd/user.c (+1/-1)
lib/core/linkedlist.c (+292/-159)
lib/core/linkedlist.h (+14/-12)
lib/core/modularization.c (+20/-20)
test/check_lib_core.c (+1/-0)
test/lib/core/linkedlist.c (+90/-0)
test/lib/core/test_suites.h (+1/-0)
To merge this branch: bzr merge lp:~stefan.goetz-deactivatedaccount/hipl/hip-ll-extensions
Reviewer Review Type Date Requested Status
Diego Biurrun Needs Fixing
Review via email: mp+56024@code.launchpad.net

Description of the change

Simplifies and extends the linked list implementation. These extensions are needed in other branches.

To post a comment you must log in.
Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (14.8 KiB)

 review needs-fixing

On Sat, Apr 02, 2011 at 01:16:36AM +0000, Stefan Götz wrote:
> Stefan Götz has proposed merging lp:~stefan.goetz/hipl/hip-ll-extensions into lp:hipl.

OK, I will try to bother you into splitting off some changes and
pushing them into trunk right away. I'd ask you to follow along.
Let's try this as an experiment and see if it leads to branches
getting merged quicker.

> --- hipd/hip_socket.c 2011-02-25 15:18:27 +0000
> +++ hipd/hip_socket.c 2011-04-02 01:16:32 +0000
> @@ -251,8 +251,8 @@
>
> int hip_get_highest_descriptor(void)
> {
> - int highest_descriptor = 0;
> - struct hip_ll_node *iter = NULL;
> + int highest_descriptor = 0;
> + const struct hip_ll_node *iter = NULL;

Push right away.

> @@ -269,7 +269,7 @@
>
> void hip_prepare_fd_set(fd_set *read_fdset)
> {
> - struct hip_ll_node *iter = NULL;
> + const struct hip_ll_node *iter = NULL;

ditto

> @@ -296,8 +296,8 @@
> */
> void hip_run_socket_handles(fd_set *read_fdset, struct hip_packet_context *ctx)
> {
> - struct hip_ll_node *iter = NULL;
> - int socketfd;
> + const struct hip_ll_node *iter = NULL;
> + int socketfd;

same

> --- hipd/maintenance.c 2011-02-14 19:20:39 +0000
> +++ hipd/maintenance.c 2011-04-02 01:16:32 +0000
> @@ -224,8 +224,8 @@
> */
> static int hip_run_maint_functions(void)
> {
> - int err = 0;
> - struct hip_ll_node *iter = NULL;
> + int err = 0;
> + const struct hip_ll_node *iter = NULL;

same

> --- hipd/pkt_handling.c 2011-02-14 18:40:02 +0000
> +++ hipd/pkt_handling.c 2011-04-02 01:16:32 +0000
> @@ -139,8 +139,8 @@
> {
> - int err = 0;
> - struct hip_ll_node *iter = NULL;
> + int err = 0;
> + const struct hip_ll_node *iter = NULL;

same

> --- hipd/registration.c 2011-03-29 19:46:16 +0000
> +++ hipd/registration.c 2011-04-02 01:16:32 +0000
> @@ -104,7 +104,7 @@
> int idx = 0;
> time_t now = time(NULL);
> - struct hip_ll_node *iter = NULL;
> + const struct hip_ll_node *iter = NULL;

this as well

> @@ -241,8 +241,8 @@
> */
> int hip_del_pending_request(struct hip_hadb_state *entry)
> {
> - int idx = 0;
> - struct hip_ll_node *iter = NULL;
> + int idx = 0;
> + const struct hip_ll_node *iter = NULL;

and this

> @@ -276,7 +276,7 @@
> {
> int idx = 0;
> - struct hip_ll_node *iter = NULL;
> + const struct hip_ll_node *iter = NULL;

and this

> @@ -308,7 +308,7 @@
> int hip_replace_pending_requests(struct hip_hadb_state *entry_old,
> struct hip_hadb_state *entry_new)
> {
> - struct hip_ll_node *iter = 0;
> + const struct hip_ll_node *iter = 0;

again

> @@ -338,8 +338,8 @@
> static int hip_get_pending_requests(struct hip_hadb_state *entry,
> struct hip_pending_request *requests[])
> {
> - struct hip_ll_node *iter ...

review: Needs Fixing
Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :

Hi Diego!

> OK, I will try to bother you into splitting off some changes and
> pushing them into trunk right away. I'd ask you to follow along.
> Let's try this as an experiment and see if it leads to branches
> getting merged quicker.

I agree with you: smaller merge proposals are easier to review and get into trunk more quickly. Where we apparently disagree is how far this approach should be taken. My personal guideline for grouping commits into a branch/merge proposal is that these commits need to be related to each other under a common topic which should make it easier to review them in context of each other as opposed to separately.

In the case of this branch, this means: this branch cleans up the hip_ll implementation. A changeset of 973 lines is not nothing, admittedly, plus one could factor out the new function with the unit tests because it's not cleanup. But this whole thing is neatly divided into well-documented commits. Turning each commit into a separate branch/merge proposal is detrimental to reviews in my opinion, because it breaks the common context which these commits share and which actually helps during review.

So I fully buy the approach to committing minor, unrelated stuff to trunk right away. It's just that I think that nothing here qualifies as 'unrelated'.

Apart from that, I agree with all your other comments except where noted below.

>> + unsigned i = 0;
>> + struct hip_ll_node *p = NULL;
>> + struct hip_ll_node *node;
>
> struct hip_ll_node *p = NULL; *node;
>
> save those precious lines :)

I couldn't find this policy in doc/HACKING. Its sample code actually follows the 'one declaration per line' style. Personally, I prefer that style, too, because a) I don't overlook declarations as easily and b) it keeps diffs cleaner and c) when I can choose between fewer lines and more readable code, I guess it's obvious which choice I'd make :-) Sorry for being a difficult customer today.

>> +/**
>> + * Get the list node with the specified index.
>> + *
>> + * @param list points to the list to search. The result of calling this
>> + * this function with list == NULL is undefined.
>> + * @param idx the index of the list node to retrieve. The first node element
>> + * has the index 0. The result of calling this function with an idx
>> + * value greater than or equal to the number of nodes in the list
>> + * is undefined.
>> + * @return the list node with the index idx.
>
> nit: s/.//

A sed expression that says 'Delete the first character of each line'? Delete all full stops? Delete the full stop at the end of each paragraph? And in any case: why? :-)

Stefan

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (3.4 KiB)

On Sat, Apr 02, 2011 at 03:12:31PM +0000, Stefan Götz wrote:
>
> > OK, I will try to bother you into splitting off some changes and
> > pushing them into trunk right away. I'd ask you to follow along.
> > Let's try this as an experiment and see if it leads to branches
> > getting merged quicker.
>
> I agree with you: smaller merge proposals are easier to review and get
> into trunk more quickly. Where we apparently disagree is how far this
> approach should be taken. My personal guideline for grouping commits
> into a branch/merge proposal is that these commits need to be related
> to each other under a common topic which should make it easier to
> review them in context of each other as opposed to separately.
>
> In the case of this branch, this means: this branch cleans up the
> hip_ll implementation. A changeset of 973 lines is not nothing,
> admittedly, plus one could factor out the new function with the unit
> tests because it's not cleanup. But this whole thing is neatly divided
> into well-documented commits. Turning each commit into a separate
> branch/merge proposal is detrimental to reviews in my opinion, because
> it breaks the common context which these commits share and which
> actually helps during review.
>
> So I fully buy the approach to committing minor, unrelated stuff to
> trunk right away. It's just that I think that nothing here qualifies
> as 'unrelated'.

The word "unrelated" is obscuring my point it seems. I mean all changes
that are independent and can be broken out of a merge proposal should be
broken out and committed separately.

I have just done this as a proof of concept for your branch. Splitting
off the const correctness changes by manually editing the diff file,
applying to a vanilla branch, recompiling, recompiling to run all tests,
writing a commit message and committing with you as author took no more
than 15 minutes.

If you go ahead and rebase your tree against trunk now your merge request
will shrink considerably and it will be quicker for me and all others to
review it.

The point is that before I had to rereview changes again that I had already
approved. I cannot just skip them since I cannot be sure they are exactly
the same as before, your tree might have changed.

After doublechecking now I see that this amounts to more or less the first
commit in your branch, which you could have pushed to trunk more easily.
Well, so possibly this has not saved much time, *but* we have more const
correctness in trunk now, not just hidden away in your branch :)

> >> +/**
> >> + * Get the list node with the specified index.
> >> + *
> >> + * @param list points to the list to search. The result of calling this
> >> + * this function with list == NULL is undefined.
> >> + * @param idx the index of the list node to retrieve. The first node element
> >> + * has the index 0. The result of calling this function with an idx
> >> + * value greater than or equal to the number of nodes in the list
> >> + * is undefined.
> >> + * @return the list node with the index idx.
> >
> > nit: s/.//
>
> A sed expression that says 'Delete the first character of each line'?
> Dele...

Read more...

Unmerged revisions

5816. By Stefan Götz

Add function for deleting a linked list element that matches specific payload data.
Add unit tests to cover this new functionality.

5815. By Stefan Götz

Add an internal, more generic function for deleting a list node from a linked list.
Simplify the hip_ll_del() function by re-using the added internal function.

5814. By Stefan Götz

Add internal functions for retrieving list nodes.
Simplify the existing functions hip_ll_add() and hip_ll_get() by re-using the added functions.

5813. By Stefan Götz

Simplify hip_ll_uninit() to re-use existing code instead of re-implementing it.

5812. By Stefan Götz

Fixed const correctness of linked list implementation. Adapted code using linked lists where necessary.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2011-03-25 17:51:40 +0000
3+++ Makefile.am 2011-04-02 01:16:32 +0000
4@@ -205,6 +205,7 @@
5
6 test_check_lib_core_SOURCES = test/check_lib_core.c \
7 test/lib/core/hit.c \
8+ test/lib/core/linkedlist.c \
9 test/lib/core/straddr.c
10
11 # Include module Makefile.am's.
12
13=== modified file 'hipd/hip_socket.c'
14--- hipd/hip_socket.c 2011-02-25 15:18:27 +0000
15+++ hipd/hip_socket.c 2011-04-02 01:16:32 +0000
16@@ -251,8 +251,8 @@
17
18 int hip_get_highest_descriptor(void)
19 {
20- int highest_descriptor = 0;
21- struct hip_ll_node *iter = NULL;
22+ int highest_descriptor = 0;
23+ const struct hip_ll_node *iter = NULL;
24
25 if (hip_sockets) {
26 while ((iter = hip_ll_iterate(hip_sockets, iter))) {
27@@ -269,7 +269,7 @@
28
29 void hip_prepare_fd_set(fd_set *read_fdset)
30 {
31- struct hip_ll_node *iter = NULL;
32+ const struct hip_ll_node *iter = NULL;
33
34 FD_ZERO(read_fdset);
35
36@@ -296,8 +296,8 @@
37 */
38 void hip_run_socket_handles(fd_set *read_fdset, struct hip_packet_context *ctx)
39 {
40- struct hip_ll_node *iter = NULL;
41- int socketfd;
42+ const struct hip_ll_node *iter = NULL;
43+ int socketfd;
44
45 if (hip_sockets) {
46 while ((iter = hip_ll_iterate(hip_sockets, iter))) {
47
48=== modified file 'hipd/maintenance.c'
49--- hipd/maintenance.c 2011-02-14 19:20:39 +0000
50+++ hipd/maintenance.c 2011-04-02 01:16:32 +0000
51@@ -224,8 +224,8 @@
52 */
53 static int hip_run_maint_functions(void)
54 {
55- int err = 0;
56- struct hip_ll_node *iter = NULL;
57+ int err = 0;
58+ const struct hip_ll_node *iter = NULL;
59
60 if (hip_maintenance_functions) {
61 while ((iter = hip_ll_iterate(hip_maintenance_functions, iter))) {
62
63=== modified file 'hipd/pkt_handling.c'
64--- hipd/pkt_handling.c 2011-02-14 18:40:02 +0000
65+++ hipd/pkt_handling.c 2011-04-02 01:16:32 +0000
66@@ -139,8 +139,8 @@
67 const uint32_t ha_state,
68 struct hip_packet_context *ctx)
69 {
70- int err = 0;
71- struct hip_ll_node *iter = NULL;
72+ int err = 0;
73+ const struct hip_ll_node *iter = NULL;
74
75 HIP_IFEL(packet_type > HIP_MAX_PACKET_TYPE,
76 -1,
77
78=== modified file 'hipd/registration.c'
79--- hipd/registration.c 2011-03-29 19:46:16 +0000
80+++ hipd/registration.c 2011-04-02 01:16:32 +0000
81@@ -104,7 +104,7 @@
82 {
83 int idx = 0;
84 time_t now = time(NULL);
85- struct hip_ll_node *iter = NULL;
86+ const struct hip_ll_node *iter = NULL;
87 struct hip_pending_request *request = NULL;
88
89 /* See hip_del_pending_request() for a comment. */
90@@ -241,8 +241,8 @@
91 */
92 int hip_del_pending_request(struct hip_hadb_state *entry)
93 {
94- int idx = 0;
95- struct hip_ll_node *iter = NULL;
96+ int idx = 0;
97+ const struct hip_ll_node *iter = NULL;
98
99 /* Iterate through the linked list. The iterator itself can't be used
100 * for deleting nodes from the list. Therefore, we just get the index of
101@@ -276,7 +276,7 @@
102 uint8_t reg_type)
103 {
104 int idx = 0;
105- struct hip_ll_node *iter = NULL;
106+ const struct hip_ll_node *iter = NULL;
107 struct hip_pending_request *request = NULL;
108
109 /* See hip_del_pending_request() for a comment. */
110@@ -308,7 +308,7 @@
111 int hip_replace_pending_requests(struct hip_hadb_state *entry_old,
112 struct hip_hadb_state *entry_new)
113 {
114- struct hip_ll_node *iter = 0;
115+ const struct hip_ll_node *iter = 0;
116
117 while ((iter = hip_ll_iterate(&pending_requests, iter)) != NULL) {
118 if (((struct hip_pending_request *) (iter->ptr))->entry == entry_old) {
119@@ -338,8 +338,8 @@
120 static int hip_get_pending_requests(struct hip_hadb_state *entry,
121 struct hip_pending_request *requests[])
122 {
123- struct hip_ll_node *iter = 0;
124- int request_count = 0;
125+ const struct hip_ll_node *iter = 0;
126+ int request_count = 0;
127
128 if (requests == NULL) {
129 return -1;
130@@ -368,8 +368,8 @@
131 */
132 static int hip_get_pending_request_count(struct hip_hadb_state *entry)
133 {
134- struct hip_ll_node *iter = 0;
135- int request_count = 0;
136+ const struct hip_ll_node *iter = 0;
137+ int request_count = 0;
138
139 while ((iter = hip_ll_iterate(&pending_requests, iter)) != NULL) {
140 if (((struct hip_pending_request *) (iter->ptr))->entry == entry) {
141
142=== modified file 'hipd/user.c'
143--- hipd/user.c 2011-03-24 17:34:21 +0000
144+++ hipd/user.c 2011-04-02 01:16:32 +0000
145@@ -185,7 +185,7 @@
146 struct hip_common *msg,
147 struct sockaddr_in6 *src)
148 {
149- struct hip_ll_node *iter = NULL;
150+ const struct hip_ll_node *iter = NULL;
151
152 if (!hip_user_msg_handles[msg_type] ||
153 !hip_ll_get_size(hip_user_msg_handles[msg_type])) {
154
155=== modified file 'lib/core/linkedlist.c'
156--- lib/core/linkedlist.c 2011-03-29 17:55:57 +0000
157+++ lib/core/linkedlist.c 2011-04-02 01:16:32 +0000
158@@ -43,7 +43,7 @@
159 *
160 * @param linkedlist the list to init.
161 */
162-void hip_ll_init(struct hip_ll *linkedlist)
163+void hip_ll_init(struct hip_ll *const linkedlist)
164 {
165 if (linkedlist != NULL) {
166 *linkedlist = (struct hip_ll) HIP_LL_INIT;
167@@ -72,34 +72,15 @@
168 * invoking this function, and then call this function with
169 * NULL as @c free_element.
170 */
171-void hip_ll_uninit(struct hip_ll *linkedlist, free_elem_fn free_element)
172+void hip_ll_uninit(struct hip_ll *const linkedlist, free_elem_fn free_element)
173 {
174- struct hip_ll_node *pointer = NULL;
175-
176- if (linkedlist == NULL || linkedlist->head == NULL) {
177- return;
178- }
179-
180- /* Free the node currently at list head and move the next item to list
181- * head. Continue this until the item at list head is NULL. If
182- * free_element() is non-NULL we also free the memory allocated for the
183- * actual element. */
184- if (free_element != NULL) {
185- while (linkedlist->head != NULL) {
186- pointer = linkedlist->head->next;
187- free_element(linkedlist->head->ptr);
188- free(linkedlist->head);
189- linkedlist->head = pointer;
190- }
191- } else {
192- while (linkedlist->head != NULL) {
193- pointer = linkedlist->head->next;
194- free(linkedlist->head);
195- linkedlist->head = pointer;
196- }
197- }
198-
199- linkedlist->element_count = 0;
200+ if (linkedlist) {
201+ while (linkedlist->head) {
202+ hip_ll_del_first(linkedlist, free_element);
203+ }
204+ HIP_ASSERT(!linkedlist->head);
205+ HIP_ASSERT(!linkedlist->element_count);
206+ }
207 }
208
209 /**
210@@ -108,7 +89,7 @@
211 * @param linkedlist the list whose node count is to be returned.
212 * @return number of nodes in the list.
213 */
214-unsigned int hip_ll_get_size(const struct hip_ll *linkedlist)
215+unsigned int hip_ll_get_size(const struct hip_ll *const linkedlist)
216 {
217 if (linkedlist == NULL) {
218 return 0;
219@@ -118,77 +99,184 @@
220 }
221
222 /**
223+ * Get the list node with the specified index and its predecessor node.
224+ *
225+ * This function helps to avoid re-implementing the linear search for different
226+ * purposes.
227+ *
228+ * @param list points to the list to search. The result of calling this
229+ * this function with list == NULL is undefined.
230+ * @param idx the index of the list node to retrieve. The first node element
231+ * has the index 0. The result of calling this function with an idx
232+ * value greater than or equal to the number of nodes in the list
233+ * is undefined.
234+ * @param prev points to a struct hip_ll_node pointer. If this function returns
235+ * successfully, the value of prev is set to point to the
236+ * predecessor node of the returned node. It is set to NULL, of the
237+ * returned node is the first node in the list.
238+ * @return the list node with the index idx.
239+ */
240+static struct hip_ll_node *hip_ll_get_node_with_prev(const struct hip_ll *const list,
241+ const unsigned idx,
242+ struct hip_ll_node **const prev)
243+{
244+ unsigned i = 0;
245+ struct hip_ll_node *p = NULL;
246+ struct hip_ll_node *node;
247+
248+ HIP_ASSERT(list);
249+ HIP_ASSERT((list->element_count == 0 && !list->head) ||
250+ (list->element_count == 1 && list->head && !list->head->next) ||
251+ (list->element_count > 1 && list->head && list->head->next));
252+ HIP_ASSERT(idx < list->element_count);
253+ HIP_ASSERT(prev);
254+
255+ for (node = list->head; node; node = node->next) {
256+ if (i != idx) {
257+ p = node;
258+ i += 1;
259+ } else {
260+ *prev = p;
261+ break;
262+ }
263+ }
264+
265+ HIP_ASSERT(node &&
266+ ((idx == 0 && !*prev) ||
267+ (*prev && (*prev)->next == node)));
268+
269+ return node;
270+}
271+
272+/**
273+ * Get the list node with the specified index.
274+ *
275+ * @param list points to the list to search. The result of calling this
276+ * this function with list == NULL is undefined.
277+ * @param idx the index of the list node to retrieve. The first node element
278+ * has the index 0. The result of calling this function with an idx
279+ * value greater than or equal to the number of nodes in the list
280+ * is undefined.
281+ * @return the list node with the index idx.
282+ */
283+static struct hip_ll_node *hip_ll_get_node(const struct hip_ll *const list,
284+ const unsigned idx)
285+{
286+ struct hip_ll_node *p = NULL;
287+
288+ return hip_ll_get_node_with_prev(list, idx, &p);
289+}
290+
291+/**
292+ * Find the first list node associated with the specified payload data and
293+ * return the list node, its index, and the predecessor node.
294+ *
295+ * This function helps to avoid re-implementing the linear search for different
296+ * purposes.
297+ *
298+ * @param list points to the list to search. The result of calling this
299+ * this function with list == NULL is undefined.
300+ * @param ptr the payload pointer to find in the list. ptr may be NULL.
301+ * @param idx points to an unsigned integer object. If this function returns
302+ * successfully, the value of the integer is set to the index of
303+ * the found list item. The result of calling this function with
304+ * idx == NULL is undefined.
305+ * @param prev points to a struct hip_ll_node pointer. If this function returns
306+ * successfully, the value of the node pointer is set to point to
307+ * the predecessor node of the returned node. It is set to NULL,
308+ * if the returned node is the first node in the list.
309+ * @return the first list node that points to the same payload data as ptr.
310+ * If no such list node can be found, this function returns NULL.
311+ */
312+static struct hip_ll_node *hip_ll_find_node_with_prev(const struct hip_ll *const list,
313+ const void *const ptr,
314+ unsigned *const idx,
315+ struct hip_ll_node **const prev)
316+{
317+ unsigned i = 0;
318+ struct hip_ll_node *p = NULL;
319+ struct hip_ll_node *node;
320+
321+ HIP_ASSERT(list);
322+ HIP_ASSERT((list->element_count == 0 && !list->head) ||
323+ (list->element_count == 1 && list->head && !list->head->next) ||
324+ (list->element_count > 1 && list->head && list->head->next));
325+ HIP_ASSERT(idx);
326+ HIP_ASSERT(prev);
327+
328+ for (node = list->head; node; node = node->next) {
329+ if (node->ptr != ptr) {
330+ p = node;
331+ i += 1;
332+ } else {
333+ *idx = i;
334+ *prev = p;
335+ break;
336+ }
337+ }
338+
339+ HIP_ASSERT(!node ||
340+ (*idx == 0 && !*prev) ||
341+ (*idx > 0 && *idx < list->element_count && *prev &&
342+ (*prev)->next == node));
343+
344+ return node;
345+}
346+
347+/**
348 * Adds a new node to a linked list. Adds a new node at @c index to the
349- * parameter @c linkedlist with payload data @c ptr. If there are less than
350- * (<code>index -1</code>) elements in the list, the element will be added as
351- * the last element of the list.
352+ * parameter @c linkedlist with payload data @c ptr. If there are exactly
353+ * <code>index</code> elements in the list, the element is added as the last
354+ * element of the list.
355 *
356 * <b>Example:</b>
357 *
358- * <code>hip_ll_add(&mylist, 2, mydata);</code> will add @c mydata as the
359- * third item of the list when there are more than two elements in @c mylist.
360- * When there are less than two items in the list @c mydata will be added as
361- * the last element of @c mylist.
362+ * <code>hip_ll_add(&mylist, 2, mydata);</code> adds @c mydata as the
363+ * third item of the list when there are two or more elements in @c mylist.
364 *
365 * @param linkedlist the list where to add the new node.
366 * @param index the list index where to store the node. Indexing starts
367 * from zero.
368 * @param ptr a pointer to the data to be stored.
369 * @return zero on success, -1 if @c linkedlist or @c ptr is NULL or
370- * if there was an error when allocating memory to the new
371- * node.
372+ * index is greater than the size of list or if there is an
373+ * error when allocating memory for the new node.
374 */
375-int hip_ll_add(struct hip_ll *linkedlist, const unsigned int index, void *ptr)
376+int hip_ll_add(struct hip_ll *const linkedlist, const unsigned int index, void *const ptr)
377 {
378- struct hip_ll_node *newnode = NULL, *pointer = NULL;
379- unsigned int current_index = 0;
380-
381- if (linkedlist == NULL || ptr == NULL) {
382- return -1;
383- }
384-
385- if ((newnode = malloc(sizeof(struct hip_ll_node))) == NULL) {
386- HIP_ERROR("Error on allocating memory for a linked list node.\n");
387- return -1;
388- }
389-
390- newnode->ptr = ptr;
391- pointer = linkedlist->head;
392-
393- /* Item to add is the first item of the list or it is to be added as the
394- * first one. */
395- if (pointer == NULL || index == 0) {
396- newnode->next = pointer;
397- linkedlist->head = newnode;
398- linkedlist->element_count++;
399- }
400- /* There exist at least one element in the list and the new element is
401- * not to be added as the first one. */
402- else {
403- struct hip_ll_node *previous = pointer;
404-
405- /* Loop until "pointer" is at the last item. */
406- while (pointer->next != NULL) {
407- previous = pointer;
408- pointer = pointer->next;
409- current_index++;
410-
411- /* We have reached the target index and the index is not
412- * the index of the last item in the list. */
413- if (current_index == index) {
414- newnode->next = pointer;
415- previous->next = newnode;
416- linkedlist->element_count++;
417- return 0;
418+ if (linkedlist && index <= linkedlist->element_count && ptr) {
419+ struct hip_ll_node *newnode;
420+ if ((newnode = malloc(sizeof(*newnode)))) {
421+ newnode->ptr = ptr;
422+
423+ if (index == 0) {
424+ newnode->next = linkedlist->head;
425+ linkedlist->head = newnode;
426+ } else {
427+ // newnode is to be inserted after prev and before next
428+ struct hip_ll_node *next = NULL;
429+ struct hip_ll_node *prev = NULL;
430+
431+ if (index != linkedlist->element_count) {
432+ next = hip_ll_get_node_with_prev(linkedlist, index, &prev);
433+ } else {
434+ prev = hip_ll_get_node(linkedlist, index - 1);
435+ next = NULL;
436+ }
437+ HIP_ASSERT(prev->next == next);
438+ prev->next = newnode;
439+ newnode->next = next;
440 }
441+
442+ linkedlist->element_count += 1;
443+
444+ return 0;
445+ } else {
446+ HIP_ERROR("Error on allocating memory for a linked list node.\n");
447 }
448- /* The node is to be added as the last item of the list. */
449- newnode->next = NULL;
450- pointer->next = newnode;
451- linkedlist->element_count++;
452 }
453
454- return 0;
455+ return -1;
456 }
457
458 /**
459@@ -201,7 +289,7 @@
460 * if there was an error when allocating memory to the new
461 * node.
462 */
463-int hip_ll_add_first(struct hip_ll *linkedlist, void *ptr)
464+int hip_ll_add_first(struct hip_ll *const linkedlist, void *const ptr)
465 {
466 return hip_ll_add(linkedlist, 0, ptr);
467 }
468@@ -216,12 +304,55 @@
469 * if there was an error when allocating memory to the new
470 * node.
471 */
472-int hip_ll_add_last(struct hip_ll *linkedlist, void *ptr)
473+int hip_ll_add_last(struct hip_ll *const linkedlist, void *const ptr)
474 {
475 return hip_ll_add(linkedlist, linkedlist->element_count, ptr);
476 }
477
478 /**
479+ * Remove a node from a list and free the node memory (not the payload data).
480+ *
481+ * Since this function expects to be given the predecessor of the node to
482+ * delete, this function has a runtime complexity of O(1).
483+ *
484+ * @param list the list from which to delete the node. The result of calling
485+ * this function with list == NULL is undefined.
486+ * @param node the node to delete. The result of calling this function with
487+ * list == NULL is undefined.
488+ * @param prev the predecessor node of the node to delete. prev must be NULL
489+ * iff node is the first node in the list. The result of calling
490+ * this function under the violation of this condition is
491+ * undefined.
492+ * @return pointer to the payload data the deleted list node was associated
493+ * with.
494+ */
495+static void *hip_ll_del_node(struct hip_ll *const list,
496+ struct hip_ll_node *const node,
497+ struct hip_ll_node *const prev)
498+{
499+ void *payload;
500+
501+ HIP_ASSERT(list);
502+ HIP_ASSERT(node);
503+ HIP_ASSERT((prev && prev->next == node) ||
504+ (!prev && list->head == node));
505+ HIP_ASSERT((list->element_count == 1 && list->head && !list->head->next) ||
506+ (list->element_count > 1 && list->head && list->head->next));
507+
508+ payload = node->ptr;
509+
510+ if (prev) {
511+ prev->next = node->next;
512+ } else {
513+ list->head = node->next;
514+ }
515+ free(node);
516+ list->element_count -= 1;
517+
518+ return payload;
519+}
520+
521+/**
522 * Deletes a node from a linked list. Deletes a node at @c index and frees the
523 * memory allocated for the node from the parameter @c linkedlist. If there are
524 * less than (<code>index -1</code>) nodes in the list no action will be taken. If
525@@ -244,58 +375,25 @@
526 * element itself is deleted. NULL is also returned when
527 * the list @c linkedlist itself is NULL.
528 */
529-void *hip_ll_del(struct hip_ll *linkedlist, const unsigned int index,
530+void *hip_ll_del(struct hip_ll *const linkedlist, const unsigned int index,
531 free_elem_fn free_element)
532 {
533- struct hip_ll_node *pointer = NULL, *previous = NULL;
534- void *ptr = NULL;
535- unsigned int current_index = 0;
536-
537- if (linkedlist == NULL || linkedlist->head == NULL) {
538- return NULL;
539- } else if (index > (linkedlist->element_count - 1)) {
540- return NULL;
541- }
542-
543- if (index == 0) {
544- ptr = linkedlist->head->ptr;
545- pointer = linkedlist->head->next;
546- if (free_element != NULL) {
547- free_element(ptr);
548- ptr = NULL;
549- }
550- free(linkedlist->head);
551- linkedlist->head = pointer;
552- linkedlist->element_count--;
553- return ptr;
554- }
555-
556- pointer = previous = linkedlist->head;
557-
558- while (pointer->next != NULL) {
559- previous = pointer;
560- pointer = pointer->next;
561- current_index++;
562-
563- /* We have reached the target index. */
564- if (current_index == index) {
565- if (pointer == NULL) {
566- previous->next = NULL;
567- } else {
568- previous->next = pointer->next;
569- }
570- ptr = pointer->ptr;
571- if (free_element != NULL) {
572- free_element(ptr);
573- ptr = NULL;
574- }
575- free(pointer);
576- linkedlist->element_count--;
577- break;
578- }
579- }
580-
581- return ptr;
582+ if (linkedlist && index < linkedlist->element_count) {
583+ struct hip_ll_node *node = NULL;
584+ struct hip_ll_node *prev = NULL;
585+ void *payload;
586+
587+ node = hip_ll_get_node_with_prev(linkedlist, index, &prev);
588+ payload = hip_ll_del_node(linkedlist, node, prev);
589+ if (free_element) {
590+ free_element(payload);
591+ return NULL;
592+ } else {
593+ return payload;
594+ }
595+ } else {
596+ return NULL;
597+ }
598 }
599
600 /**
601@@ -317,13 +415,60 @@
602 * deleted. NULL is also returned when the list
603 * @c linkedlist itself is NULL.
604 */
605-void *hip_ll_del_first(struct hip_ll *linkedlist,
606+void *hip_ll_del_first(struct hip_ll *const linkedlist,
607 free_elem_fn free_element)
608 {
609 return hip_ll_del(linkedlist, 0, free_element);
610 }
611
612 /**
613+ * Delete the first list element which contains the specified payload data
614+ * item from a linked list.
615+ *
616+ * @param list points to the list from which to delete the element.
617+ * The result of calling this function with
618+ * list == NULL is undefined.
619+ * @param ptr points to payload data which has previously been added
620+ * to list via one of the hip_ll_add() functions. If
621+ * no list element contains ptr, no list element is deleted.
622+ * @param free_element points to an optional callback function that is called
623+ * when a list element matches ptr, typically in order to
624+ * free the memory associated with ptr. If free_element is
625+ * NULL, the list element is removed from list but
626+ * the memory associated with the list element is not freed
627+ * and returned by this function instead. If free_element
628+ * is not NULL, the payload ptr should have been added to
629+ * list only once. Otherwise, the latter list
630+ * elements referring to ptr point to de-allocated memory.
631+ * @return NULL if the payload ptr is not in list. Returns
632+ * NULL if the payload ptr is found in list and
633+ * free_element is not NULL. Returns ptr if the payload ptr
634+ * is found in the list and free_element is NULL.
635+ */
636+void *hip_ll_del_by_payload(struct hip_ll *const list,
637+ void *const ptr,
638+ free_elem_fn free_element)
639+{
640+ if (list) {
641+ struct hip_ll_node *node = NULL;
642+ struct hip_ll_node *prev = NULL;
643+ unsigned idx = 0;
644+
645+ node = hip_ll_find_node_with_prev(list, ptr, &idx, &prev);
646+ if (node) {
647+ hip_ll_del_node(list, node, prev);
648+ if (!free_element) {
649+ return ptr;
650+ } else {
651+ free_element(ptr);
652+ }
653+ }
654+ }
655+
656+ return NULL;
657+}
658+
659+/**
660 * Gets an element from a linked list. Returns a pointer to the payload data
661 * stored in node at @c index. When there are less than (<code>index -1</code>)
662 * nodes in the list, no action will be taken.
663@@ -334,27 +479,15 @@
664 * @return the next element or NULL if the list end has been reached
665 * or if @c linkedlist is NULL.
666 */
667-void *hip_ll_get(struct hip_ll *linkedlist, const unsigned int index)
668+void *hip_ll_get(const struct hip_ll *const linkedlist, const unsigned int index)
669 {
670- struct hip_ll_node *pointer = linkedlist->head;
671- unsigned int current_index = 0;
672-
673- if (linkedlist == NULL || linkedlist->head == NULL) {
674- return NULL;
675- } else if (index > (linkedlist->element_count - 1)) {
676- return NULL;
677- }
678-
679- while (pointer != NULL) {
680- if (current_index == index) {
681- break;
682- }
683-
684- pointer = pointer->next;
685- current_index++;
686- }
687-
688- return pointer->ptr;
689+ if (linkedlist && index < linkedlist->element_count) {
690+ struct hip_ll_node *const node = hip_ll_get_node(linkedlist, index);
691+ HIP_ASSERT(node);
692+ return node->ptr;
693+ } else {
694+ return NULL;
695+ }
696 }
697
698 /**
699@@ -379,8 +512,8 @@
700 * using this function.</span> Consider hip_ll_del() or
701 * hip_ll_uninit() for deleting nodes and elements.
702 */
703-struct hip_ll_node *hip_ll_iterate(const struct hip_ll *linkedlist,
704- struct hip_ll_node *current)
705+const struct hip_ll_node *hip_ll_iterate(const struct hip_ll *const linkedlist,
706+ const struct hip_ll_node *const current)
707 {
708 if (linkedlist == NULL) {
709 return NULL;
710
711=== modified file 'lib/core/linkedlist.h'
712--- lib/core/linkedlist.h 2011-03-29 16:48:08 +0000
713+++ lib/core/linkedlist.h 2011-04-02 01:16:32 +0000
714@@ -61,19 +61,21 @@
715 #define HIP_LL_INIT { 0, NULL }
716
717 /** Linked list element memory deallocator function pointer. */
718-typedef void (*free_elem_fn)(void *ptr);
719+typedef void (*free_elem_fn)(void *const ptr);
720
721-void hip_ll_init(struct hip_ll *linkedlist);
722-void hip_ll_uninit(struct hip_ll *linkedlist, free_elem_fn free_element);
723-unsigned int hip_ll_get_size(const struct hip_ll *linkedlist);
724-int hip_ll_add(struct hip_ll *linkedlist, const unsigned int index, void *ptr);
725-int hip_ll_add_first(struct hip_ll *linkedlist, void *ptr);
726-int hip_ll_add_last(struct hip_ll *linkedlist, void *ptr);
727-void *hip_ll_del(struct hip_ll *linkedlist, const unsigned int index,
728+void hip_ll_init(struct hip_ll *const linkedlist);
729+void hip_ll_uninit(struct hip_ll *const linkedlist, free_elem_fn free_element);
730+unsigned int hip_ll_get_size(const struct hip_ll *const linkedlist);
731+int hip_ll_add(struct hip_ll *const linkedlist, const unsigned int index, void *const ptr);
732+int hip_ll_add_first(struct hip_ll *const linkedlist, void *const ptr);
733+int hip_ll_add_last(struct hip_ll *const linkedlist, void *const ptr);
734+void *hip_ll_del(struct hip_ll *const linkedlist, const unsigned int index,
735 free_elem_fn free_element);
736-void *hip_ll_del_first(struct hip_ll *linkedlist, free_elem_fn free_element);
737-void *hip_ll_get(struct hip_ll *linkedlist, const unsigned int index);
738-struct hip_ll_node *hip_ll_iterate(const struct hip_ll *linkedlist,
739- struct hip_ll_node *current);
740+void *hip_ll_del_first(struct hip_ll *const linkedlist, free_elem_fn free_element);
741+void *hip_ll_del_by_payload(struct hip_ll *const list, void *const ptr,
742+ free_elem_fn free_element);
743+void *hip_ll_get(const struct hip_ll *const linkedlist, const unsigned int index);
744+const struct hip_ll_node *hip_ll_iterate(const struct hip_ll *const linkedlist,
745+ const struct hip_ll_node *const current);
746
747 #endif /* HIP_LIB_CORE_LINKEDLIST_H */
748
749=== modified file 'lib/core/modularization.c'
750--- lib/core/modularization.c 2011-04-01 12:30:35 +0000
751+++ lib/core/modularization.c 2011-04-02 01:16:32 +0000
752@@ -165,8 +165,8 @@
753 */
754 void lmod_init_state_items(struct modular_state *state)
755 {
756- struct hip_ll_node *iter = NULL;
757- int (*init_function)(struct modular_state *state) = NULL;
758+ const struct hip_ll_node *iter = NULL;
759+ int (*init_function)(struct modular_state *state) = NULL;
760
761 while ((iter = hip_ll_iterate(&state_init_functions, iter))) {
762 init_function = iter->ptr;
763@@ -300,9 +300,9 @@
764 void *entry,
765 const uint16_t priority)
766 {
767- int idx = 0;
768- struct hip_ll *new_list = NULL;
769- struct hip_ll_node *iter = NULL;
770+ int idx = 0;
771+ struct hip_ll *new_list = NULL;
772+ const struct hip_ll_node *iter = NULL;
773
774 if (!list) {
775 if (!(new_list = malloc(sizeof(struct hip_ll)))) {
776@@ -342,8 +342,8 @@
777 */
778 int lmod_unregister_function(struct hip_ll *list, const void *function)
779 {
780- int idx = 0;
781- struct hip_ll_node *iter = NULL;
782+ int idx = 0;
783+ const struct hip_ll_node *iter = NULL;
784
785 if (!list) {
786 return -1;
787@@ -440,8 +440,8 @@
788 */
789 int lmod_packet_type_exists(const uint8_t packet_type)
790 {
791- int idx = 0;
792- struct hip_ll_node *iter = NULL;
793+ int idx = 0;
794+ const struct hip_ll_node *iter = NULL;
795
796 while ((iter = hip_ll_iterate(&packet_types, iter))) {
797 if (packet_type == ((struct packet_type *) iter->ptr)->num) {
798@@ -461,7 +461,7 @@
799 */
800 const char *lmod_get_packet_identifier(const uint8_t packet_type)
801 {
802- struct hip_ll_node *iter = NULL;
803+ const struct hip_ll_node *iter = NULL;
804 HIP_DEBUG("Name search for packet type %d \n", packet_type);
805
806 while ((iter = hip_ll_iterate(&packet_types, iter))) {
807@@ -489,9 +489,9 @@
808 int lmod_register_packet_type(const uint8_t packet_type,
809 const char *const identifier)
810 {
811- int idx = 0;
812- struct hip_ll_node *iter = NULL;
813- struct packet_type *new_entry = NULL;
814+ int idx = 0;
815+ const struct hip_ll_node *iter = NULL;
816+ struct packet_type *new_entry = NULL;
817
818 if (!identifier || (lmod_packet_type_exists(packet_type) != -1)) {
819 return -1;
820@@ -559,8 +559,8 @@
821 */
822 int lmod_parameter_type_exists(const uint16_t parameter_type)
823 {
824- int index = 0;
825- struct hip_ll_node *iter = NULL;
826+ int index = 0;
827+ const struct hip_ll_node *iter = NULL;
828
829 while ((iter = hip_ll_iterate(&parameter_types, iter))) {
830 if (parameter_type == ((struct parameter_type *) iter->ptr)->num) {
831@@ -589,10 +589,10 @@
832 int lmod_register_parameter_type(const uint16_t parameter_type,
833 const char *const identifier)
834 {
835- int index = 0;
836- struct hip_ll_node *iter = NULL;
837- struct parameter_type *new_entry = NULL;
838- int err = 0;
839+ int index = 0;
840+ const struct hip_ll_node *iter = NULL;
841+ struct parameter_type *new_entry = NULL;
842+ int err = 0;
843
844 HIP_IFEL(!identifier || (lmod_parameter_type_exists(parameter_type) != -1),
845 -1, "Missing identifier or parameter type already registered.\n");
846@@ -633,7 +633,7 @@
847 */
848 const char *lmod_get_parameter_identifier(const uint16_t parameter_type)
849 {
850- struct hip_ll_node *iter = NULL;
851+ const struct hip_ll_node *iter = NULL;
852 HIP_DEBUG("Name search for parameter type %d \n", parameter_type);
853
854 while ((iter = hip_ll_iterate(&parameter_types, iter))) {
855
856=== modified file 'test/check_lib_core.c'
857--- test/check_lib_core.c 2011-02-18 14:39:38 +0000
858+++ test/check_lib_core.c 2011-04-02 01:16:32 +0000
859@@ -38,6 +38,7 @@
860 {
861 int number_failed;
862 SRunner *sr = srunner_create(lib_core_hit());
863+ srunner_add_suite(sr, lib_core_linkedlist());
864 srunner_add_suite(sr, lib_core_straddr());
865
866 srunner_run_all(sr, CK_NORMAL);
867
868=== added file 'test/lib/core/linkedlist.c'
869--- test/lib/core/linkedlist.c 1970-01-01 00:00:00 +0000
870+++ test/lib/core/linkedlist.c 2011-04-02 01:16:32 +0000
871@@ -0,0 +1,90 @@
872+/*
873+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
874+ *
875+ * Permission is hereby granted, free of charge, to any person
876+ * obtaining a copy of this software and associated documentation
877+ * files (the "Software"), to deal in the Software without
878+ * restriction, including without limitation the rights to use,
879+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
880+ * copies of the Software, and to permit persons to whom the
881+ * Software is furnished to do so, subject to the following
882+ * conditions:
883+ *
884+ * The above copyright notice and this permission notice shall be
885+ * included in all copies or substantial portions of the Software.
886+ *
887+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
888+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
889+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
890+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
891+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
892+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
893+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
894+ * OTHER DEALINGS IN THE SOFTWARE.
895+ */
896+
897+/**
898+ * @file
899+ * @author Stefan Goetz <stefan.goetz@cs.rwth-aachen.de>
900+ */
901+
902+#include <check.h>
903+#include <stdlib.h>
904+
905+#include "lib/core/linkedlist.h"
906+#include "test_suites.h"
907+
908+static struct hip_ll *list;
909+
910+static void cleanup(void *const p)
911+{
912+ fail_unless(p == list);
913+};
914+
915+START_TEST(test_hip_ll_del_by_payload_without_cleanup)
916+{
917+ struct hip_ll l;
918+ hip_ll_init(&l);
919+ hip_ll_add_first(&l, &l);
920+ fail_unless(hip_ll_del_by_payload(&l, &l, NULL) == &l, NULL);
921+ fail_unless(hip_ll_get_size(&l) == 0, NULL);
922+}
923+END_TEST START_TEST(test_hip_ll_del_by_payload_with_cleanup)
924+{
925+ list = malloc(sizeof(*list));
926+ hip_ll_init(list);
927+ hip_ll_add_first(list, list);
928+ fail_unless(hip_ll_del_by_payload(list, list, cleanup) == NULL, NULL);
929+ fail_unless(hip_ll_get_size(list) == 0, NULL);
930+ free(list);
931+}
932+
933+END_TEST START_TEST(test_hip_ll_del_by_payload_with_invalid_payload)
934+{
935+ struct hip_ll l;
936+ hip_ll_init(&l);
937+ hip_ll_add_first(&l, &l);
938+ fail_unless(hip_ll_del_by_payload(&l, NULL, NULL) == NULL, NULL);
939+ fail_unless(hip_ll_get_size(&l) == 1, NULL);
940+}
941+
942+END_TEST START_TEST(test_hip_ll_del_by_payload_with_invalid_list)
943+{
944+ fail_unless(hip_ll_del_by_payload(NULL, NULL, NULL) == NULL, NULL);
945+}
946+
947+END_TEST
948+
949+Suite *lib_core_linkedlist(void)
950+{
951+ Suite *s = suite_create("lib/core/linkedlist");
952+
953+ TCase *tc_linkedlist = tcase_create("Linked List");
954+ tcase_add_test(tc_linkedlist, test_hip_ll_del_by_payload_without_cleanup);
955+ tcase_add_test(tc_linkedlist, test_hip_ll_del_by_payload_with_cleanup);
956+ tcase_add_test(tc_linkedlist, test_hip_ll_del_by_payload_with_invalid_payload);
957+ tcase_add_test(tc_linkedlist, test_hip_ll_del_by_payload_with_invalid_list);
958+ suite_add_tcase(s, tc_linkedlist);
959+
960+ return s;
961+}
962
963=== modified file 'test/lib/core/test_suites.h'
964--- test/lib/core/test_suites.h 2011-02-18 14:39:38 +0000
965+++ test/lib/core/test_suites.h 2011-04-02 01:16:32 +0000
966@@ -29,6 +29,7 @@
967 #include <check.h>
968
969 Suite *lib_core_hit(void);
970+Suite *lib_core_linkedlist(void);
971 Suite *lib_core_straddr(void);
972
973 #endif /* HIP_TEST_LIB_CORE_TEST_SUITES_H */

Subscribers

People subscribed via source and target branches

to all changes: