反省してなかった

いや、意外と便利だぜこれ。vectorのコピペ。

#ifndef STACK_H
#define STACK_H

#define DEFAULT_STACK_SIZE 256

#define STACK_PROTOTYPE(type)                                   \
    typedef struct type##_stack_ {                              \
        type * data;                                            \
                                                                \
        int size;                                               \
        int index;                                              \
    } * type##_stack_t;                                         \
                                                                \
    type##_stack_t make_##type##_stack();                       \
    void type##_stack_expand(type##_stack_t stk);               \
    void delete_##type##_stack(type##_stack_t stk);             \
                                                                \
    type type##_stack_top(type##_stack_t stk);                  \
    type type##_stack_pop(type##_stack_t stk);                  \
    void type##_stack_push(type##_stack_t stk, type value);     \
    bool type##_stack_empty(type##_stack_t stk);                \
    int type##_stack_length(type##_stack_t stk);

#define STACK_BODY(type)                                                \
    type##_stack_t make_##type##_stack(){                               \
        type##_stack_t ret;                                             \
        SAFE_MALLOC(ret, sizeof(struct type##_stack_));                 \
        SAFE_CALLOC(ret->data, DEFAULT_STACK_SIZE, sizeof(type));       \
                                                                        \
        ret->size = DEFAULT_STACK_SIZE;                                 \
        ret->index = 0;                                                 \
                                                                        \
        return ret;                                                     \
    }                                                                   \
    void stack_##type##_expand(type##_stack_t stk){                     \
        SAFE_REALLOC(stk->data, sizeof(type) * stk->size * 2);          \
        int i = stk->size;                                              \
        for(;i < stk->size * 2; i++){                                   \
            stk->data[i] = (type)0;                                     \
        }                                                               \
        stk->size *= 2;                                                 \
    }                                                                   \
    void delete_##type##_stack(type##_stack_t stk){                     \
        free(stk->data);                                                \
        free(stk);                                                      \
    }                                                                   \
                                                                        \
    type type##_stack_top(type##_stack_t stk){                          \
        if (stk->index == 0){                                           \
            return (type)0;                                             \
        }                                                               \
                                                                        \
        return stk->data[stk->index - 1];                               \
    }                                                                   \
    type type##_stack_pop(type##_stack_t stk){                          \
        if (stk->index == 0){                                           \
            return (type)0;                                             \
        }                                                               \
                                                                        \
        return stk->data[--stk->index];                                 \
    }                                                                   \
    void type##_stack_push(type##_stack_t stk, type value){             \
        while(stk->index >= stk->size){                                 \
            stack_##type##_expand(stk);                                 \
        }                                                               \
                                                                        \
        stk->data[stk->index++] = value;                                \
    }                                                                   \
    bool type##_stack_empty(type##_stack_t stk){                        \
        if (stk->index == 0) return TRUE;                               \
        else return FALSE;                                              \
    }                                                                   \
    int type##_stack_length(type##_stack_t stk){                        \
        return stk->index;                                              \
    }

#define STACK_DEFINE(type) \
    STACK_PROTOTYPE(type); \
    STACK_BODY(type)

#endif

テストケースも書いたよ(> <)!!

#include "test.h"
#include "stack.h"

/* STACK_DEFINE(int) */
STACK_PROTOTYPE(int);
STACK_BODY(int);

STACK_DEFINE(char);
STACK_DEFINE(double);

int main(int argc, char * argv[]){

    int_stack_t istk = make_int_stack();

    TEST_ASSERT(int_stack_empty(istk) == TRUE);
    TEST_ASSERT(int_stack_top(istk) == 0);

    int_stack_push(istk, 12345);
    TEST_ASSERT(int_stack_empty(istk) == FALSE);
    TEST_ASSERT(int_stack_top(istk) == 12345);
    TEST_ASSERT(int_stack_pop(istk) == 12345);
    TEST_ASSERT(int_stack_empty(istk) == TRUE);

    int_stack_push(istk, 12345);
    int_stack_push(istk, 23456);
    int_stack_push(istk, 34567);

    TEST_ASSERT(int_stack_empty(istk) == FALSE);
    TEST_ASSERT(int_stack_top(istk) == 34567);
    TEST_ASSERT(int_stack_pop(istk) == 34567);
    TEST_ASSERT(int_stack_empty(istk) == FALSE);
    TEST_ASSERT(int_stack_top(istk) == 23456);
    TEST_ASSERT(int_stack_pop(istk) == 23456);
    TEST_ASSERT(int_stack_empty(istk) == FALSE);
    TEST_ASSERT(int_stack_top(istk) == 12345);
    TEST_ASSERT(int_stack_pop(istk) == 12345);
    TEST_ASSERT(int_stack_empty(istk) == TRUE);

    delete_int_stack(istk);

    
    char_stack_t cstk = make_char_stack();

    TEST_ASSERT(char_stack_empty(cstk) == TRUE);
    TEST_ASSERT(char_stack_top(cstk) == 0);

    char_stack_push(cstk, 123);
    TEST_ASSERT(char_stack_empty(cstk) == FALSE);
    TEST_ASSERT(char_stack_top(cstk) == 123);
    TEST_ASSERT(char_stack_pop(cstk) == 123);
    TEST_ASSERT(char_stack_empty(cstk) == TRUE);

    char_stack_push(cstk, 123);
    char_stack_push(cstk, 23);
    char_stack_push(cstk, 67);

    TEST_ASSERT(char_stack_empty(cstk) == FALSE);
    TEST_ASSERT(char_stack_top(cstk) == 67);
    TEST_ASSERT(char_stack_pop(cstk) == 67);
    TEST_ASSERT(char_stack_empty(cstk) == FALSE);
    TEST_ASSERT(char_stack_top(cstk) == 23);
    TEST_ASSERT(char_stack_pop(cstk) == 23);
    TEST_ASSERT(char_stack_empty(cstk) == FALSE);
    TEST_ASSERT(char_stack_top(cstk) == 123);
    TEST_ASSERT(char_stack_pop(cstk) == 123);
    TEST_ASSERT(char_stack_empty(cstk) == TRUE);

    delete_char_stack(cstk);


    
    double_stack_t dstk = make_double_stack();

    TEST_ASSERT(double_stack_empty(dstk) == TRUE);
    TEST_ASSERT(double_stack_top(dstk) == 0);

    double_stack_push(dstk, 12.345);
    TEST_ASSERT(double_stack_empty(dstk) == FALSE);
    TEST_ASSERT(double_stack_top(dstk) == 12.345);
    TEST_ASSERT(double_stack_pop(dstk) == 12.345);
    TEST_ASSERT(double_stack_empty(dstk) == TRUE);

    double_stack_push(dstk, 12.345);
    double_stack_push(dstk, 0.0023456);
    double_stack_push(dstk, 34567e10);

    TEST_ASSERT(double_stack_empty(dstk) == FALSE);
    TEST_ASSERT(double_stack_top(dstk) == 34567e10);
    TEST_ASSERT(double_stack_pop(dstk) == 34567e10);
    TEST_ASSERT(double_stack_empty(dstk) == FALSE);
    TEST_ASSERT(double_stack_top(dstk) == 0.0023456);
    TEST_ASSERT(double_stack_pop(dstk) == 0.0023456);
    TEST_ASSERT(double_stack_empty(dstk) == FALSE);
    TEST_ASSERT(double_stack_top(dstk) == 12.345);
    TEST_ASSERT(double_stack_pop(dstk) == 12.345);
    TEST_ASSERT(double_stack_empty(dstk) == TRUE);

    delete_double_stack(dstk);


    return 0;
}