summaryrefslogtreecommitdiff
path: root/src/tc-list.c
blob: e8a30b68387f93030cdf4c1b900167766ea5eee5 (plain)
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// 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 int 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)
			return EXIT_FAILURE;
#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);
	}
	return EXIT_SUCCESS;
}

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);
#ifdef __cplusplus
		delete obj;
#else
		free(obj);
#endif
	}

	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
}

static int runner(int argc, const char **argv)
{
	unsigned int max = 10;

	if (HX_init() <= 0)
		return EXIT_FAILURE;
	if (argc >= 2)
		max = strtoul(argv[1], NULL, 0);
	int ret = l_init(max, HX_rand() & 1);
	if (ret != EXIT_SUCCESS)
		return ret;
	l_traverse();
	l_dump(HX_rand() & 1);
	l_empty();
	l_shift();
	HX_exit();
	return EXIT_SUCCESS;
}

int main(int argc, const char **argv)
{
	int ret = runner(argc, argv);
	if (ret != EXIT_FAILURE)
		fprintf(stderr, "FAILED\n");
	return ret;
}