zring_t * zring_dup (zring_t *self) { if (!self) return NULL; zring_t *copy = zring_new (); if (copy) { copy->destructor = self->destructor; copy->duplicator = self->duplicator; copy->comparator = self->comparator; node_t *node; for (node = self->head->next; node != self->head; node = node->next) { void *item = node->item; if (self->duplicator) item = self->duplicator (item); if (!item || zring_append (copy, item)) { zring_destroy (©); break; } } } return copy; }
int zring_insert (zring_t *self, const void *key, void *item) { assert (self); assert (key); assert (item); if (!self->hash) self->hash = zhash_new (); if (!self->hash) return -1; // If item isn't already in dictionary, append to list and then // store item node (which is in cursor) in dictionary if (!zhash_lookup (self->hash, key) && !zring_append (self, item) && !zhash_insert (self->hash, key, self->cursor)) { self->cursor->key = zhash_cursor (self->hash); return 0; } else return -1; }
zring_t * zring_dup (zring_t *self) { // Duplicating a null reference returns a null reference if (!self) return NULL; zring_t *copy = zring_new (); if (copy) { copy->free_fn = self->free_fn; copy->dup_fn = self->dup_fn; node_t *node; for (node = self->head.next; node != &self->head; node = node->next) { void *item = node->item; if (self->dup_fn) item = self->dup_fn (item); if (zring_append (copy, item)) { zring_destroy (©); break; } } } return copy; }
void zring_test (int verbose) { printf (" * zring: "); // @selftest zring_t *ring = zring_new (); assert (ring); assert (zring_size (ring) == 0); // Three items we'll use as test data // Ring items are void *, not particularly strings char *cheese = "boursin"; char *bread = "baguette"; char *wine = "bordeaux"; int rc = zring_append (ring, cheese); assert (!rc); assert (zring_size (ring) == 1); rc = zring_append (ring, bread); assert (!rc); assert (zring_size (ring) == 2); rc = zring_append (ring, wine); assert (!rc); assert (zring_size (ring) == 3); assert (zring_next (ring) == cheese); assert (zring_first (ring) == cheese); assert (zring_next (ring) == bread); assert (zring_next (ring) == wine); assert (zring_next (ring) == NULL); // After we reach end of ring, next wraps around assert (zring_next (ring) == cheese); assert (zring_last (ring) == wine); assert (zring_prev (ring) == bread); assert (zring_prev (ring) == cheese); assert (zring_prev (ring) == NULL); // After we reach start of ring, prev wraps around assert (zring_prev (ring) == wine); assert (zring_first (ring) == cheese); zring_remove (ring); assert (zring_size (ring) == 2); assert (zring_first (ring) == bread); zring_remove (ring); assert (zring_size (ring) == 1); assert (zring_first (ring) == wine); zring_remove (ring); assert (zring_size (ring) == 0); assert (zring_first (ring) == NULL); rc = zring_push (ring, cheese); assert (!rc); assert (zring_size (ring) == 1); assert (zring_first (ring) == cheese); rc = zring_push (ring, bread); assert (!rc); assert (zring_size (ring) == 2); assert (zring_first (ring) == bread); rc = zring_append (ring, wine); assert (!rc); assert (zring_size (ring) == 3); assert (zring_first (ring) == bread); zring_t *dup_ring = zring_dup (ring); assert (dup_ring); assert (zring_size (dup_ring) == 3); // Destructor should be safe to call twice zring_destroy (&ring); assert (ring == NULL); zring_destroy (&ring); // @end printf ("OK\n"); }
void zring_test (int verbose) { printf (" * zring: "); // @selftest zring_t *ring = zring_new (); assert (ring); assert (zring_size (ring) == 0); // Three items we'll use as test data // Ring items are void *, not particularly strings char *cheese = "boursin"; char *bread = "baguette"; char *wine = "bordeaux"; int rc = zring_append (ring, cheese); assert (!rc); assert (zring_size (ring) == 1); assert (zring_item (ring) == cheese); rc = zring_append (ring, bread); assert (!rc); assert (zring_size (ring) == 2); assert (zring_item (ring) == bread); rc = zring_append (ring, wine); assert (!rc); assert (zring_size (ring) == 3); assert (zring_item (ring) == wine); assert (zring_first (ring) == cheese); assert (zring_next (ring) == bread); assert (zring_next (ring) == wine); assert (zring_next (ring) == NULL); // After we reach end of ring, next wraps around assert (zring_next (ring) == cheese); assert (zring_last (ring) == wine); assert (zring_prev (ring) == bread); assert (zring_prev (ring) == cheese); assert (zring_prev (ring) == NULL); // After we reach start of ring, prev wraps around assert (zring_prev (ring) == wine); zring_purge (ring); // Test some list insertion-deletion combos assert (zring_size (ring) == 0); zring_prepend (ring, "4"); zring_append (ring, "3"); zring_prepend (ring, "5"); zring_append (ring, "2"); zring_prepend (ring, "0"); zring_append (ring, "1"); assert (zring_size (ring) == 6); // Try the comparator functionality zring_set_comparator (ring, (czmq_comparator *) strcmp); zring_sort (ring); char *item = (char *) zring_first (ring); assert (streq (item, "0")); item = (char *) zring_find (ring, "5"); assert (streq (item, "5")); // Try the duplicator and destructor zring_set_duplicator (ring, (czmq_duplicator *) strdup); zring_t *dup = zring_dup (ring); assert (dup); zring_set_destructor (dup, (czmq_destructor *) zstr_free); assert (zring_size (dup) == 6); zring_destroy (&dup); // We're comparing as strings, not item pointers rc = zring_remove (ring, "2"); assert (rc == 0); rc = zring_remove (ring, "5"); assert (rc == 0); rc = zring_remove (ring, "3"); assert (rc == 0); item = (char *) zring_detach (ring, NULL); zring_purge (ring); // Try the dictionary insert/delete functionality rc = zring_insert (ring, "1", "one"); assert (rc == 0); rc = zring_insert (ring, "3", "three"); assert (rc == 0); rc = zring_insert (ring, "2", "two"); assert (rc == 0); rc = zring_insert (ring, "2", "two"); assert (rc == -1); item = (char *) zring_lookup (ring, "2"); assert (streq (item, "two")); item = (char *) zring_lookup (ring, "1"); assert (streq (item, "one")); item = (char *) zring_item (ring); assert (streq (item, "one")); rc = zring_delete (ring, "3"); assert (rc == 0); rc = zring_delete (ring, "3"); assert (rc == -1); // Using detach/remove will also remove from dictionary rc = zring_remove (ring, "two"); assert (rc == 0); rc = zring_delete (ring, "2"); assert (rc == -1); zring_purge (ring); // Destructor should be safe to call twice zring_destroy (&ring); assert (ring == NULL); zring_destroy (&ring); // @end printf ("OK\n"); }