1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
// SPDX-License-Identifier: MIT
#ifdef __cplusplus
# include <cstdio>
# include <cstdlib>
#else
# include <stdbool.h>
# include <stdio.h>
# include <stdlib.h>
#endif
#include <libHX/list.h>
#include <libHX/init.h>
#include <libHX/misc.h>
struct text_object {
struct HXlist_head list;
char id[5];
};
union list_encap {
struct HXlist_head list;
};
static HXCLIST_HEAD(strings_ct);
static void l_init(unsigned int max, bool unshift)
{
static const char *const msg[] = {"Pushing", "Unshifting"};
struct text_object *obj;
unsigned int i;
for (i = 1; i <= max; ++i) {
#ifdef __cplusplus
obj = new struct text_object;
#else
obj = malloc(sizeof(*obj));
if (obj == NULL)
abort();
#endif
HXlist_init(&obj->list);
obj->id[0] = HX_irand('a', 'z'+1);
obj->id[1] = HX_irand('a', 'z'+1);
obj->id[2] = HX_irand('a', 'z'+1);
obj->id[3] = HX_irand('a', 'z'+1);
obj->id[4] = '\0';
printf("%s item %u (\"%s\")\n", msg[unshift], i, obj->id);
if (unshift)
HXclist_unshift(&strings_ct, &obj->list);
else
HXclist_push(&strings_ct, &obj->list);
}
}
static void l_traverse(void)
{
const struct text_object *obj, *safe;
unsigned int i;
i = 0;
HXlist_for_each_entry_safe(obj, safe, &strings_ct, list)
printf("Retrieving item %u (\"%s\")\n", ++i, obj->id);
}
static void l_dump(bool pop)
{
static const char *const msg[] = {"Shifting", "Popping"};
struct text_object *obj;
unsigned int i = 0;
while ((obj = (pop ?
HXclist_pop(&strings_ct, struct text_object, list) :
HXclist_shift(&strings_ct, struct text_object, list)
)) != NULL)
printf("%s item %u (\"%s\")\n", msg[pop], ++i, obj->id);
printf("Remaining elements: %u\n", strings_ct.items);
}
static void l_empty(void)
{
static const char *const fstr[] = {"fail", "pass"};
struct HXclist_head clh;
struct HXlist_head lh;
union list_encap *pos;
unsigned int count = 0;
bool success = true;
HXlist_init(&lh);
HXclist_init(&clh);
HXlist_for_each_entry(pos, &lh, list)
success = false;
HXlist_for_each_entry(pos, &clh, list)
success = false;
printf("Zero traversal: %s\n", fstr[success]);
printf("The list is indeed%s empty\n",
HXlist_empty(&lh) ? "" : " NOT");
HXclist_push(&clh, &lh);
HXlist_for_each_entry(pos, &clh, list)
++count;
printf("One traversal: %s\n", fstr[count == 1]);
printf("The list is indeed%s empty\n",
HXlist_empty(&lh) ? "" : " NOT");
}
static void l_shift(void)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
/* Check for -Wshadow warnings */
struct object {
int value;
struct HXlist_head anchor;
};
HXCLIST_HEAD(clh);
struct object q, *p;
void *x;
q.value = 1337;
HXlist_init(&q.anchor);
HXclist_push(&clh, &q.anchor);
x = p = HXclist_shift(&clh, struct object, anchor);
printf("%d\n", p->value);
HXlist_init(&q.anchor);
HXclist_push(&clh, &q.anchor);
x = p = HXclist_pop(&clh, struct object, anchor);
printf("%d\n", p->value);
#pragma GCC diagnostic pop
}
int main(int argc, const char **argv)
{
unsigned int max = 10;
if (HX_init() <= 0)
abort();
if (argc >= 2)
max = strtoul(argv[1], NULL, 0);
l_init(max, HX_rand() & 1);
l_traverse();
l_dump(HX_rand() & 1);
l_empty();
l_shift();
HX_exit();
return EXIT_SUCCESS;
}
|