#include <stdlib.h>
#include "stack.h"

//DONE: grundlegende Stackfunktionen implementieren:
/*  * `push`: legt ein Element oben auf den Stack,
    * `pop`: entfernt das oberste Element,
    * `top`: liefert das oberste Element zurück,
    * `clearStack`: gibt den gesamten Speicher frei. */

// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data)
{
    //        ,-→ Wenn keine Daten angegeben wird die Liste unverändert zurückgegeben
    if (data != NULL)
    {
        StackNode *newNode;
        newNode = (StackNode *)malloc(sizeof(StackNode));
        if (!newNode) 
            printf("Speicherfehler: nicht genug Speicher");
            return stack;

        newNode->data = data;
        
        //         ,-→ bedeutet Liste war leer - das neue Element hat keinen Nachfolger (next = NULL)
        if (stack == NULL) {
            newNode->next = NULL;
        } else {
            newNode->next = stack;
        }
        stack = newNode;
    }
    
    return stack;
}

// Deletes the top element of the stack (latest added element) and releases its memory.
// (Pointer to data has to be freed by caller.)
StackNode *pop(StackNode *stack)
{
    if(stack != NULL)
    {
        StackNode *nextNode = stack->next;
        free(stack);
        stack = nextNode;
    }
    return stack;
}

// Returns the data of the top element.
void *top(StackNode *stack)
{
    if (stack != NULL) {
        return stack->data;
    } else {
        return NULL;
    } 
}

// Clears stack and releases all memory.
void clearStack(StackNode *stack)
{
    while (stack != NULL) {
        stack = pop(stack);
    }
}
