Venom
Venom

Reputation: 1047

GLib stack data type?

Does GLib have a data type that can be used as a LIFO (stack) collection? It does have lists, queues, hash tables and such but I can't seem to find a stack data type.

There is a trash stack type but it was designed with a specific purpose in mind and it has also been deprecated since version 2.48.

What can be used as a stack in GLib?

Upvotes: 2

Views: 1274

Answers (3)

Richard Fuchs
Richard Fuchs

Reputation: 26

A bit late to the party, but a more light-weight approach to a stack would be using the singly-linked list type GSList, which doesn't require an explicit container object.

GSList *stack = NULL;
// push:
stack = g_slist_prepend(stack, element);
// stack non-empty?
if (stack) { ... }
// peek head without popping:
element = stack->data;
// pop:
stack = g_slist_delete_link(stack, stack);

A wrapper function for a proper "pop" that returns the element could then look something like this:

void *stack_pop(GSList **stackp) {
    if (!*stackp)
        return;
    void *ret = (*stackp)->data;
    *stackp = g_slist_delete_link(*stackp, *stackp);
    return ret;
}
// ...
element = stack_pop(&stack); // returns NULL if stack is empty

Upvotes: 1

Dov Grobgeld
Dov Grobgeld

Reputation: 4983

I needed the same thing so I wrote this trivial example:

// An example stack in glib using a Queue. As this example uses
// integers, we make use of the glib GPOINTER_TO_UINT macros.
//
// Compile by:
//    cc `pkg-config --cflags --libs glib-2.0` -o test-stack test-stack.c

#include <glib.h>
#include <stdio.h>
#include <stdint.h>

void pintqueue(GQueue *q)
{
    int i;
    printf("[%d] ", q->length);

    GList *h = q->head;

    for (i=0; i<q->length; i++) {
        printf("%d ", (int)GPOINTER_TO_UINT(h->data));
        h=h->next;
    }
    printf("\n");
}

void qintpush(GQueue *q, gint val)
{
    g_queue_push_tail(q, GUINT_TO_POINTER((guint)val));
}

gint qintpop(GQueue *q)
{
    if (q->length==0) {
        // "Error handling"
        g_message("Ooops! Trying to pop from an empty stack!");
        return INT_MAX;
    }
    return (gint)(GPOINTER_TO_UINT(g_queue_pop_tail(q)));
}

gint main(int argc, char **argv)
{
    GQueue q = G_QUEUE_INIT;

    qintpush(&q, 34);
    qintpush(&q, 42);
    qintpush(&q, -1);

    pintqueue(&q);

    printf("Popped: %d\n", qintpop(&q));
    pintqueue(&q);

    for (int i=0; i<5; i++)
        printf("Popped: %d\n", qintpop(&q));

    exit(0);
}

Upvotes: 2

Marichyasana
Marichyasana

Reputation: 3154

Never used it, but from the documentation you should be able to use a double ended queue. To put onto stack use g_queue_push_head() and to pop from stack use g_queue_pop_head() see: https://people.gnome.org/~desrt/glib-docs/glib-Double-ended-Queues.html

Upvotes: 3

Related Questions