source: mainline/uspace/lib/pcut/src/list.c@ a05ec66

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a05ec66 was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 * Copyright (c) 2012-2013 Vojtech Horky
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file
30 *
31 * Helper functions for working with list of items.
32 */
33
34#include <assert.h>
35#include <stdlib.h>
36#include "internal.h"
37#include <pcut/pcut.h>
38
39
40/** Find next item with actual content.
41 *
42 * @param item Head of the list.
43 * @return First item with actual content or NULL on end of list.
44 */
45pcut_item_t *pcut_get_real_next(pcut_item_t *item)
46{
47 if (item == NULL) {
48 return NULL;
49 }
50
51 do {
52 item = item->next;
53 } while ((item != NULL) && (item->kind == PCUT_KIND_SKIP));
54
55
56 return item;
57}
58
59/** Retrieve the first item with actual content.
60 *
61 * Unlike pcut_get_real_next(), where we always advance after the
62 * first item, here the @p item itself could be returned.
63 *
64 * @param item Head of the list.
65 * @return First item with actual content or NULL on end of list.
66 */
67pcut_item_t *pcut_get_real(pcut_item_t *item)
68{
69 if (item == NULL) {
70 return NULL;
71 }
72
73 if (item->kind == PCUT_KIND_SKIP) {
74 return pcut_get_real_next(item);
75 } else {
76 return item;
77 }
78}
79
80
81/** In-line nested lists into the parent.
82 *
83 * @param nested Head of the nested list.
84 */
85static void inline_nested_lists(pcut_item_t *nested)
86{
87 pcut_item_t *first;
88
89 if (nested->kind != PCUT_KIND_NESTED) {
90 return;
91 }
92
93 if (nested->nested == NULL) {
94 nested->kind = PCUT_KIND_SKIP;
95 return;
96 }
97
98 first = pcut_fix_list_get_real_head(nested->nested);
99 nested->nested->next = nested->next;
100 if (nested->next != NULL) {
101 nested->next->previous = nested->nested;
102 }
103 nested->next = first;
104 first->previous = nested;
105
106 nested->kind = PCUT_KIND_SKIP;
107}
108
109/** Assing unique ids to each item in the list.
110 *
111 * @param first List head.
112 */
113static void set_ids(pcut_item_t *first)
114{
115 int id = 1;
116 pcut_item_t *it;
117
118 assert(first != NULL);
119
120 if (first->kind == PCUT_KIND_SKIP) {
121 first = pcut_get_real_next(first);
122 }
123
124 for (it = first; it != NULL; it = pcut_get_real_next(it)) {
125 it->id = id;
126 id++;
127 }
128}
129
130/** Hide tests that are marked to be skipped.
131 *
132 * Go through all tests and those that have PCUT_EXTRA_SKIP mark
133 * as skipped with PCUT_KIND_SKIP.
134 *
135 * @param first Head of the list.
136 */
137static void detect_skipped_tests(pcut_item_t *first)
138{
139 pcut_item_t *it;
140
141 assert(first != NULL);
142 if (first->kind == PCUT_KIND_SKIP) {
143 first = pcut_get_real_next(first);
144 }
145
146 for (it = first; it != NULL; it = pcut_get_real_next(it)) {
147 pcut_extra_t *extras;
148
149 if (it->kind != PCUT_KIND_TEST) {
150 continue;
151 }
152
153 extras = it->extras;
154 while (extras->type != PCUT_EXTRA_LAST) {
155 if (extras->type == PCUT_EXTRA_SKIP) {
156 it->kind = PCUT_KIND_SKIP;
157 break;
158 }
159 extras++;
160 }
161 }
162}
163
164/** Convert the static single-linked list into a flat double-linked list.
165 *
166 * The conversion includes
167 * * adding forward links
168 * * flattening of any nested lists
169 * * assigning of unique ids
170 *
171 * @param last Tail of the list.
172 * @return Head of the fixed list.
173 */
174pcut_item_t *pcut_fix_list_get_real_head(pcut_item_t *last)
175{
176 pcut_item_t *next, *it;
177
178 last->next = NULL;
179
180 inline_nested_lists(last);
181
182 next = last;
183 it = last->previous;
184 while (it != NULL) {
185 it->next = next;
186 inline_nested_lists(it);
187 next = it;
188 it = it->previous;
189 }
190
191 detect_skipped_tests(next);
192
193 set_ids(next);
194
195 return next;
196}
197
198/** Compute the number of all tests in a list.
199 *
200 * @param it Head of the list.
201 * @return Number of tests.
202 */
203int pcut_count_tests(pcut_item_t *it)
204{
205 int count = 0;
206 while (it != NULL) {
207 if (it->kind == PCUT_KIND_TEST) {
208 count++;
209 }
210 it = pcut_get_real_next(it);
211 }
212 return count;
213}
Note: See TracBrowser for help on using the repository browser.