//-----------------------------------------------------------------------
//
// Copyright (c) SekraSoft. All rights reserved.
//
//-----------------------------------------------------------------------
#ifndef MCALC_STACK
#define MCALC_STACK
#include
// создаёт быстрый стек без операций для массивов
#define STACK_FAST(type, maxsize, size, data, \
init, deinit, push, pop, get, link) \
STACK_INIT(type, maxsize, size, data, init, deinit) \
STACK_STD_FAST(type, maxsize, size, data, push, pop, get, link)
// создаёт стек без операций для массивов
#define STACK_STD(type, maxsize, size, data, \
init, deinit, push, pop, get, link) \
STACK_INIT(type, maxsize, size, data, init, deinit) \
STACK_STD_ADV(type, maxsize, size, data, push, pop, get, link)
// создаёт стек без операций для массивов с возможностью только добавления
#define STACK_ADD(type, maxsize, size, data, \
init, deinit, push, link) \
STACK_INIT(type, maxsize, size, data, init, deinit) \
STACK_PUSH_ADV(type, maxsize, size, data, push, link)
// создаёт быстрый стек c операциями для массивов
#define STACK_ADV(type, maxsize, size, data, \
init, deinit, push, pop, get, \
aalloc, afree, aget, link) \
STACK_INIT(type, maxsize, size, data, init, deinit) \
STACK_STD_FAST(type, maxsize, size, data, push, pop, get, link) \
STACK_ARRAY(type, maxsize, size, data, aalloc, afree, aget)
// макрос создаёт функции для инициализации/удаления стека
#define STACK_INIT(type, maxsize, size, data, \
init, deinit) \
size_t maxsize = 0; \
size_t size = 0; \
type *data = 0; \
int init(size_t startsize){ \
if (startsize < 2) return 0; \
if (!(data = malloc(sizeof(type) * startsize))) return 0; \
size = 0; \
maxsize = startsize; \
return 1; \
} \
void deinit(){ if(data) free(data); data = 0; }
// простые и быстрые операции для работы со стеком
#define STACK_STD_FAST(type, maxsize, \
size, data, \
push, pop, get, link) \
void push(type link elem) { \
if (size >= maxsize){ \
type *new_data = (type*)realloc(data, \
(maxsize + (maxsize>>1)) * sizeof(type)); \
if (!new_data) return; \
data = new_data; \
maxsize += (maxsize>>1); \
} \
data[size] = link elem; \
++size; \
} \
type link void pop() { \
if (size > 0) return link data[--size]; \
return (type link)0; \
} \
type link get() { \
if (size > 0) return link data[size - 1]; \
return (type link)0; \
}
// операция push для работы со стеком, возвращающая результат
#define STACK_PUSH_ADV(type, maxsize, \
size, data, \
push, link) \
int push(type link elem) { \
if (size >= maxsize){ \
type *new_data = (type*)realloc(data, \
(maxsize + (maxsize>>1)) * sizeof(type)); \
if (!new_data) return 0; \
data = new_data; \
maxsize += (maxsize>>1); \
} \
data[size] = link elem; \
++size; \
return 1; \
}
// операции для работы со стеком, возвращающие результат
#define STACK_STD_ADV(type, maxsize, \
size, data, \
push, pop, get, link) \
STACK_PUSH_ADV(type, maxsize, size, \
data, push, link) \
int pop(type* elem) { \
if (size > 0){ \
*elem = data[--size]; \
return 1; \
} \
return 0; \
} \
int get(type* elem) { \
if (size > 0){ \
*elem = data[size - 1]; \
return 1; \
} \
return 0; \
}
// макрос создаёт функции для выделения массивов на стеке
#define STACK_ARRAY(type, maxsize, \
size, data, \
aalloc, afree, aget) \
size_t aalloc(size_t length){ \
size_t arr; \
if (size + length >= maxsize){ \
type *new_data = (type*)realloc(data, \
(size + length + (maxsize>>1)) * \
sizeof(type)); \
if (!new_data) return 0; \
data = new_data; \
maxsize = size + length + (maxsize>>1); \
} \
arr = size; \
size += length; \
return arr; \
} \
void afree(size_t length){ \
if (size < length){ \
size = 0; \
return; \
} \
size -= length; \
} \
type* aget(){ return data; }
#endif