1ZLISTX(3) CZMQ Manual ZLISTX(3)
2
3
4
6 zlistx - Class for extended generic list container
7
9 // This is a stable class, and may not change except for emergencies. It
10 // is provided in stable builds.
11 // This class has draft methods, which may change over time. They are not
12 // in stable releases, by default. Use --enable-drafts to enable.
13 // Destroy an item
14 typedef void (zlistx_destructor_fn) (
15 void **item);
16
17 // Duplicate an item
18 typedef void * (zlistx_duplicator_fn) (
19 const void *item);
20
21 // Compare two items, for sorting
22 typedef int (zlistx_comparator_fn) (
23 const void *item1, const void *item2);
24
25 // Create a new, empty list.
26 CZMQ_EXPORT zlistx_t *
27 zlistx_new (void);
28
29 // Destroy a list. If an item destructor was specified, all items in the
30 // list are automatically destroyed as well.
31 CZMQ_EXPORT void
32 zlistx_destroy (zlistx_t **self_p);
33
34 // Add an item to the head of the list. Calls the item duplicator, if any,
35 // on the item. Resets cursor to list head. Returns an item handle on
36 // success, NULL if memory was exhausted.
37 CZMQ_EXPORT void *
38 zlistx_add_start (zlistx_t *self, void *item);
39
40 // Add an item to the tail of the list. Calls the item duplicator, if any,
41 // on the item. Resets cursor to list head. Returns an item handle on
42 // success, NULL if memory was exhausted.
43 CZMQ_EXPORT void *
44 zlistx_add_end (zlistx_t *self, void *item);
45
46 // Return the number of items in the list
47 CZMQ_EXPORT size_t
48 zlistx_size (zlistx_t *self);
49
50 // Return first item in the list, or null, leaves the cursor
51 CZMQ_EXPORT void *
52 zlistx_head (zlistx_t *self);
53
54 // Return last item in the list, or null, leaves the cursor
55 CZMQ_EXPORT void *
56 zlistx_tail (zlistx_t *self);
57
58 // Return the item at the head of list. If the list is empty, returns NULL.
59 // Leaves cursor pointing at the head item, or NULL if the list is empty.
60 CZMQ_EXPORT void *
61 zlistx_first (zlistx_t *self);
62
63 // Return the next item. At the end of the list (or in an empty list),
64 // returns NULL. Use repeated zlistx_next () calls to work through the list
65 // from zlistx_first (). First time, acts as zlistx_first().
66 CZMQ_EXPORT void *
67 zlistx_next (zlistx_t *self);
68
69 // Return the previous item. At the start of the list (or in an empty list),
70 // returns NULL. Use repeated zlistx_prev () calls to work through the list
71 // backwards from zlistx_last (). First time, acts as zlistx_last().
72 CZMQ_EXPORT void *
73 zlistx_prev (zlistx_t *self);
74
75 // Return the item at the tail of list. If the list is empty, returns NULL.
76 // Leaves cursor pointing at the tail item, or NULL if the list is empty.
77 CZMQ_EXPORT void *
78 zlistx_last (zlistx_t *self);
79
80 // Returns the value of the item at the cursor, or NULL if the cursor is
81 // not pointing to an item.
82 CZMQ_EXPORT void *
83 zlistx_item (zlistx_t *self);
84
85 // Returns the handle of the item at the cursor, or NULL if the cursor is
86 // not pointing to an item.
87 CZMQ_EXPORT void *
88 zlistx_cursor (zlistx_t *self);
89
90 // Returns the item associated with the given list handle, or NULL if passed
91 // in handle is NULL. Asserts that the passed in handle points to a list element.
92 CZMQ_EXPORT void *
93 zlistx_handle_item (void *handle);
94
95 // Find an item in the list, searching from the start. Uses the item
96 // comparator, if any, else compares item values directly. Returns the
97 // item handle found, or NULL. Sets the cursor to the found item, if any.
98 CZMQ_EXPORT void *
99 zlistx_find (zlistx_t *self, void *item);
100
101 // Detach an item from the list, using its handle. The item is not modified,
102 // and the caller is responsible for destroying it if necessary. If handle is
103 // null, detaches the first item on the list. Returns item that was detached,
104 // or null if none was. If cursor was at item, moves cursor to previous item,
105 // so you can detach items while iterating forwards through a list.
106 CZMQ_EXPORT void *
107 zlistx_detach (zlistx_t *self, void *handle);
108
109 // Detach item at the cursor, if any, from the list. The item is not modified,
110 // and the caller is responsible for destroying it as necessary. Returns item
111 // that was detached, or null if none was. Moves cursor to previous item, so
112 // you can detach items while iterating forwards through a list.
113 CZMQ_EXPORT void *
114 zlistx_detach_cur (zlistx_t *self);
115
116 // Delete an item, using its handle. Calls the item destructor if any is
117 // set. If handle is null, deletes the first item on the list. Returns 0
118 // if an item was deleted, -1 if not. If cursor was at item, moves cursor
119 // to previous item, so you can delete items while iterating forwards
120 // through a list.
121 CZMQ_EXPORT int
122 zlistx_delete (zlistx_t *self, void *handle);
123
124 // Move an item to the start of the list, via its handle.
125 CZMQ_EXPORT void
126 zlistx_move_start (zlistx_t *self, void *handle);
127
128 // Move an item to the end of the list, via its handle.
129 CZMQ_EXPORT void
130 zlistx_move_end (zlistx_t *self, void *handle);
131
132 // Remove all items from the list, and destroy them if the item destructor
133 // is set.
134 CZMQ_EXPORT void
135 zlistx_purge (zlistx_t *self);
136
137 // Sort the list. If an item comparator was set, calls that to compare
138 // items, otherwise compares on item value. The sort is not stable, so may
139 // reorder equal items.
140 CZMQ_EXPORT void
141 zlistx_sort (zlistx_t *self);
142
143 // Create a new node and insert it into a sorted list. Calls the item
144 // duplicator, if any, on the item. If low_value is true, starts searching
145 // from the start of the list, otherwise searches from the end. Use the item
146 // comparator, if any, to find where to place the new node. Returns a handle
147 // to the new node, or NULL if memory was exhausted. Resets the cursor to the
148 // list head.
149 CZMQ_EXPORT void *
150 zlistx_insert (zlistx_t *self, void *item, bool low_value);
151
152 // Move an item, specified by handle, into position in a sorted list. Uses
153 // the item comparator, if any, to determine the new location. If low_value
154 // is true, starts searching from the start of the list, otherwise searches
155 // from the end.
156 CZMQ_EXPORT void
157 zlistx_reorder (zlistx_t *self, void *handle, bool low_value);
158
159 // Make a copy of the list; items are duplicated if you set a duplicator
160 // for the list, otherwise not. Copying a null reference returns a null
161 // reference.
162 CZMQ_EXPORT zlistx_t *
163 zlistx_dup (zlistx_t *self);
164
165 // Set a user-defined deallocator for list items; by default items are not
166 // freed when the list is destroyed.
167 CZMQ_EXPORT void
168 zlistx_set_destructor (zlistx_t *self, zlistx_destructor_fn destructor);
169
170 // Set a user-defined duplicator for list items; by default items are not
171 // copied when the list is duplicated.
172 CZMQ_EXPORT void
173 zlistx_set_duplicator (zlistx_t *self, zlistx_duplicator_fn duplicator);
174
175 // Set a user-defined comparator for zlistx_find and zlistx_sort; the method
176 // must return -1, 0, or 1 depending on whether item1 is less than, equal to,
177 // or greater than, item2.
178 CZMQ_EXPORT void
179 zlistx_set_comparator (zlistx_t *self, zlistx_comparator_fn comparator);
180
181 // Self test of this class.
182 CZMQ_EXPORT void
183 zlistx_test (bool verbose);
184
185 #ifdef CZMQ_BUILD_DRAFT_API
186 // *** Draft method, for development use, may change without warning ***
187 // Unpack binary frame into a new list. Packed data must follow format
188 // defined by zlistx_pack. List is set to autofree. An empty frame
189 // unpacks to an empty list.
190 CZMQ_EXPORT zlistx_t *
191 zlistx_unpack (zframe_t *frame);
192
193 // *** Draft method, for development use, may change without warning ***
194 // Serialize list to a binary frame that can be sent in a message.
195 // The packed format is compatible with the 'strings' type implemented by zproto:
196 //
197 // ; A list of strings
198 // list = list-count *longstr
199 // list-count = number-4
200 //
201 // ; Strings are always length + text contents
202 // longstr = number-4 *VCHAR
203 //
204 // ; Numbers are unsigned integers in network byte order
205 // number-4 = 4OCTET
206 // Caller owns return value and must destroy it when done.
207 CZMQ_EXPORT zframe_t *
208 zlistx_pack (zlistx_t *self);
209
210 #endif // CZMQ_BUILD_DRAFT_API
211 Please add '@interface' section in './../src/zlistx.c'.
212
214 Provides a generic doubly-linked list container. This container
215 provides hooks for duplicator, comparator, and destructor functions.
216 These tie into CZMQ and standard C semantics, so e.g. for string items
217 you can use strdup, strcmp, and zstr_free. To store custom objects,
218 define your own duplicator and comparator, and use the standard object
219 destructor.
220
221 This is a reworking of the simpler zlist container. It is faster to
222 insert and delete items anywhere in the list, and to keep ordered
223 lists.
224
226 From zlistx_test method.
227
228 zlistx_t *list = zlistx_new ();
229 assert (list);
230 assert (zlistx_size (list) == 0);
231
232 // Test operations on an empty list
233 assert (zlistx_head (list) == NULL);
234 assert (zlistx_first (list) == NULL);
235 assert (zlistx_last (list) == NULL);
236 assert (zlistx_next (list) == NULL);
237 assert (zlistx_prev (list) == NULL);
238 assert (zlistx_find (list, "hello") == NULL);
239 assert (zlistx_delete (list, NULL) == -1);
240 assert (zlistx_detach (list, NULL) == NULL);
241 assert (zlistx_delete (list, NULL) == -1);
242 assert (zlistx_detach (list, NULL) == NULL);
243 zlistx_purge (list);
244 zlistx_sort (list);
245
246 // Use item handlers
247 zlistx_set_destructor (list, (zlistx_destructor_fn *) zstr_free);
248 zlistx_set_duplicator (list, (zlistx_duplicator_fn *) strdup);
249 zlistx_set_comparator (list, (zlistx_comparator_fn *) strcmp);
250
251 // Try simple insert/sort/delete/next
252 assert (zlistx_next (list) == NULL);
253 zlistx_add_end (list, "world");
254 assert (streq ((char *) zlistx_next (list), "world"));
255 assert (streq ((char *) zlistx_head (list), "world"));
256 zlistx_add_end (list, "hello");
257 assert (streq ((char *) zlistx_prev (list), "hello"));
258 zlistx_sort (list);
259 assert (zlistx_size (list) == 2);
260 void *handle = zlistx_find (list, "hello");
261 char *item1 = (char *) zlistx_item (list);
262 char *item2 = (char *) zlistx_handle_item (handle);
263 assert (item1 == item2);
264 assert (streq (item1, "hello"));
265 zlistx_delete (list, handle);
266 assert (zlistx_size (list) == 1);
267 char *string = (char *) zlistx_detach (list, NULL);
268 assert (streq (string, "world"));
269 freen (string);
270 assert (zlistx_size (list) == 0);
271
272 // Check next/back work
273 // Now populate the list with items
274 zlistx_add_start (list, "five");
275 zlistx_add_end (list, "six");
276 zlistx_add_start (list, "four");
277 zlistx_add_end (list, "seven");
278 zlistx_add_start (list, "three");
279 zlistx_add_end (list, "eight");
280 zlistx_add_start (list, "two");
281 zlistx_add_end (list, "nine");
282 zlistx_add_start (list, "one");
283 zlistx_add_end (list, "ten");
284
285 // Test our navigation skills
286 assert (zlistx_size (list) == 10);
287 assert (streq ((char *) zlistx_last (list), "ten"));
288 assert (streq ((char *) zlistx_prev (list), "nine"));
289 assert (streq ((char *) zlistx_prev (list), "eight"));
290 assert (streq ((char *) zlistx_prev (list), "seven"));
291 assert (streq ((char *) zlistx_prev (list), "six"));
292 assert (streq ((char *) zlistx_prev (list), "five"));
293 assert (streq ((char *) zlistx_first (list), "one"));
294 assert (streq ((char *) zlistx_next (list), "two"));
295 assert (streq ((char *) zlistx_next (list), "three"));
296 assert (streq ((char *) zlistx_next (list), "four"));
297
298 // Sort by alphabetical order
299 zlistx_sort (list);
300 assert (streq ((char *) zlistx_first (list), "eight"));
301 assert (streq ((char *) zlistx_last (list), "two"));
302
303 // Moving items around
304 handle = zlistx_find (list, "six");
305 zlistx_move_start (list, handle);
306 assert (streq ((char *) zlistx_first (list), "six"));
307 zlistx_move_end (list, handle);
308 assert (streq ((char *) zlistx_last (list), "six"));
309 zlistx_sort (list);
310 assert (streq ((char *) zlistx_last (list), "two"));
311
312 // Copying a list
313 zlistx_t *copy = zlistx_dup (list);
314 assert (copy);
315 assert (zlistx_size (copy) == 10);
316 assert (streq ((char *) zlistx_first (copy), "eight"));
317 assert (streq ((char *) zlistx_last (copy), "two"));
318 zlistx_destroy (©);
319
320 // Delete items while iterating
321 string = (char *) zlistx_first (list);
322 assert (streq (string, "eight"));
323 string = (char *) zlistx_next (list);
324 assert (streq (string, "five"));
325 zlistx_delete (list, zlistx_cursor (list));
326 string = (char *) zlistx_next (list);
327 assert (streq (string, "four"));
328
329 // Test pack/unpack methods
330 zframe_t *frame = zlistx_pack (list);
331 copy = zlistx_unpack (frame);
332 assert (copy);
333 zframe_destroy (&frame);
334 assert (zlistx_size (copy) == zlistx_size (list));
335
336 char *item_orig = (char *) zlistx_first (list);
337 char *item_copy = (char *) zlistx_first (copy);
338 while (item_orig) {
339 assert (strcmp(item_orig, item_copy) == 0);
340 item_orig = (char *) zlistx_next (list);
341 item_copy = (char *) zlistx_next (copy);
342 }
343
344 zlistx_destroy (©);
345
346 zlistx_purge (list);
347 zlistx_destroy (&list);
348
349 #if defined (__WINDOWS__)
350 zsys_shutdown();
351 #endif
352
353
355 The czmq manual was written by the authors in the AUTHORS file.
356
358 Main web site:
359
360 Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
361
363 Copyright (c) the Contributors as noted in the AUTHORS file. This file
364 is part of CZMQ, the high-level C binding for 0MQ:
365 http://czmq.zeromq.org. This Source Code Form is subject to the terms
366 of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
367 distributed with this file, You can obtain one at
368 http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
369 distribution.
370
372 1. zeromq-dev@lists.zeromq.org
373 mailto:zeromq-dev@lists.zeromq.org
374
375
376
377CZMQ 4.2.1 07/19/2023 ZLISTX(3)