1 /* This file is part of Mailfromd.
2    Copyright (C) 2005-2021 Sergey Poznyakoff
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 
21 #include <stdlib.h>
22 #include <mailutils/alloc.h>
23 #include "mailfromd.h"
24 
25 struct mf_stack {
26 	char *base;
27 	size_t tos;
28 	size_t elsize;
29 	size_t elcount;
30 };
31 
32 #define STACK_PTR(s, n) (void*)((s)->base + (n) * (s)->elsize)
33 
34 mf_stack_t
mf_stack_create(size_t elsize,size_t count)35 mf_stack_create(size_t elsize, size_t count)
36 {
37 	mf_stack_t stk = mu_alloc(sizeof *stk);
38 	stk->elsize = elsize;
39 	stk->base = NULL;
40 	if (!count)
41 		count = 64;
42 	stk->elcount = count;
43 	stk->base = mu_2nrealloc(stk->base,
44 			       &stk->elcount,
45 			       stk->elsize);
46 	stk->tos = 0;
47 	return stk;
48 }
49 
50 void
mf_stack_destroy(mf_stack_t * pstk)51 mf_stack_destroy(mf_stack_t *pstk)
52 {
53 	free((*pstk)->base);
54 	free(*pstk);
55 	*pstk = NULL;
56 }
57 
58 void
mf_stack_push(mf_stack_t stk,void * item)59 mf_stack_push(mf_stack_t stk, void *item)
60 {
61 	if (stk->tos == stk->elcount)
62 		stk->base = mu_2nrealloc(stk->base,
63 				       &stk->elcount,
64 				       stk->elsize);
65 	memcpy(STACK_PTR(stk, stk->tos), item, stk->elsize);
66 	stk->tos++;
67 }
68 
69 int
mf_stack_pop(mf_stack_t stk,void * ptr)70 mf_stack_pop(mf_stack_t stk, void *ptr)
71 {
72 	if (stk->tos == 0)
73 		return 1;
74 	--stk->tos;
75 	if (ptr)
76 		memcpy(ptr, STACK_PTR(stk, stk->tos), stk->elsize);
77 	return 0;
78 }
79 
80 int
mf_stack_peek(mf_stack_t stk,size_t n,void * ptr)81 mf_stack_peek(mf_stack_t stk, size_t n, void *ptr)
82 {
83 	if (stk->tos == 0 || n + 1 > stk->tos)
84 		return 1;
85 	if (ptr)
86 		memcpy(ptr, STACK_PTR(stk, stk->tos - 1 - n), stk->elsize);
87 	return 0;
88 }
89 
90 size_t
mf_stack_count(mf_stack_t stk)91 mf_stack_count(mf_stack_t stk)
92 {
93 	return stk->tos;
94 }
95 
96 int
mf_stack_enumerate_desc(mf_stack_t stk,mf_stack_enumerator fun,void * data)97 mf_stack_enumerate_desc(mf_stack_t stk, mf_stack_enumerator fun, void *data)
98 {
99 	size_t i;
100 	for (i = stk->tos; i > 0; i--) {
101 		int rc = fun(STACK_PTR(stk, i - 1), data);
102 		if (rc)
103 			return rc;
104 	}
105 	return 0;
106 }
107 
108 int
mf_stack_enumerate_asc(mf_stack_t stk,mf_stack_enumerator fun,void * data)109 mf_stack_enumerate_asc(mf_stack_t stk, mf_stack_enumerator fun, void *data)
110 {
111 	size_t i;
112 	for (i = 0; i < stk->tos; i++) {
113 		int rc = fun(STACK_PTR(stk, i), data);
114 		if (rc)
115 			return rc;
116 	}
117 	return 0;
118 }
119 
120