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