1 /*******************************************************************************
2  * Copyright (c) 2013-2021, Andrés Martinelli <andmarti@gmail.com>             *
3  * All rights reserved.                                                        *
4  *                                                                             *
5  * This file is a part of SC-IM                                                *
6  *                                                                             *
7  * SC-IM is a spreadsheet program that is based on SC. The original authors    *
8  * of SC are James Gosling and Mark Weiser, and mods were later added by       *
9  * Chuck Martin.                                                               *
10  *                                                                             *
11  * Redistribution and use in source and binary forms, with or without          *
12  * modification, are permitted provided that the following conditions are met: *
13  * 1. Redistributions of source code must retain the above copyright           *
14  *    notice, this list of conditions and the following disclaimer.            *
15  * 2. Redistributions in binary form must reproduce the above copyright        *
16  *    notice, this list of conditions and the following disclaimer in the      *
17  *    documentation and/or other materials provided with the distribution.     *
18  * 3. All advertising materials mentioning features or use of this software    *
19  *    must display the following acknowledgement:                              *
20  *    This product includes software developed by Andrés Martinelli            *
21  *    <andmarti@gmail.com>.                                                    *
22  * 4. Neither the name of the Andrés Martinelli nor the                        *
23  *   names of other contributors may be used to endorse or promote products    *
24  *   derived from this software without specific prior written permission.     *
25  *                                                                             *
26  * THIS SOFTWARE IS PROVIDED BY ANDRES MARTINELLI ''AS IS'' AND ANY            *
27  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   *
28  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE      *
29  * DISCLAIMED. IN NO EVENT SHALL ANDRES MARTINELLI BE LIABLE FOR ANY           *
30  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  *
31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;*
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
33  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  *
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE       *
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.           *
36  *******************************************************************************/
37 
38 /**
39  * \file buffer.c
40  * \author Andrés Martinelli <andmarti@gmail.com>
41  * \date 2017-07-18
42  * \brief TODO Write a brief file description.
43  */
44 
45 #include <stdlib.h>
46 #include <wchar.h>
47 
48 #include "buffer.h"
49 #include "macros.h"
50 #include "utils/string.h"
51 
52 /**
53 * \brief Create buffer as list of blocks
54 *
55 * \return b
56 */
57 
create_buf()58 struct block * create_buf() {
59     struct block * b = (struct block *) malloc(sizeof(struct block));
60     b->value = '\0';
61     b->pnext = NULL;
62     return b;
63 }
64 
65 /**
66 * \brief Add a wint_t to a buffer
67 *
68 * \param[in] buf
69 * \param[in] d
70 *
71 * \return none
72 */
73 
addto_buf(struct block * buf,wint_t d)74 void addto_buf(struct block * buf, wint_t d) {
75     struct block * aux = buf;
76 
77     if (buf->value == '\0') {
78         buf->value = d;
79     } else {
80         struct block * b = (struct block *) malloc(sizeof(struct block));
81         b->value = d;
82         b->pnext = NULL;
83 
84         while (aux->pnext != NULL)
85             aux = aux->pnext;
86         aux->pnext = b;
87     }
88     return;
89 }
90 
91 /**
92 * \brief Replace the elements of "origen" buffer to "destino" buffer
93 *
94 * \param[in] origen
95 * \param[in] destino
96 *
97 * \return none
98 */
99 
copybuffer(struct block * origen,struct block * destino)100 void copybuffer(struct block * origen, struct block * destino) {
101     flush_buf(destino);
102     int len = get_bufsize(origen);
103     int i;
104     for (i=0; i < len; i++)
105         addto_buf(destino, get_bufval(origen, i));
106     return;
107 }
108 
109 
110 /**
111 * \brief Replace the element of a buffer at 'pos' with a '\0'
112 *
113 * \param[in] buf
114 * \param[in] pos
115 *
116 * \return none
117 */
118 
119 // FIXME
del_buf(struct block * buf,int pos)120 void del_buf (struct block * buf, int pos) {
121     int i;
122     struct block * ant = buf;
123     struct block * cur = buf;
124     for (i = 0; i < pos; i++) {
125         ant = cur;
126         cur = cur->pnext;
127     }
128     if (ant == cur) {
129         cur->value = '\0';
130         //buf = cur->pnext; //FIXME
131         //free(cur);
132     } else {
133         ant->pnext = cur->pnext;
134         free(cur);
135     }
136     return;
137 }
138 
139 /**
140 * \brief TODO Document flush_buf()
141 *
142 * \param[in] buf
143 *
144 * \return none
145 */
146 
flush_buf(struct block * buf)147 void flush_buf (struct block * buf) {
148     if (buf == NULL) return;
149 
150     struct block * aux, * np;
151     for (aux = buf->pnext; aux != NULL; aux = np) {
152         np = aux->pnext;
153         free(aux);
154     }
155     buf->value = '\0';
156     buf->pnext = NULL;
157 
158     return;
159 }
160 
161 /**
162 * \brief Delete all blocks of a buffer including the initial node
163 *
164 * \details Delete all blocks of a buffer including the initial node
165 *
166 * \param buf
167 *
168 * \return none
169 */
170 
erase_buf(struct block * buf)171 void erase_buf (struct block * buf) {
172     flush_buf(buf);
173     free(buf);
174     return;
175 }
176 
177 /**
178 * \brief Get size of buffer (included special chars)
179 *
180 * \param[in] buf
181 *
182 * \return c size of buffer
183 */
184 
get_bufsize(struct block * buf)185 int get_bufsize(struct block * buf) {
186     struct block * b_aux = buf;
187     if (b_aux == NULL || b_aux->value == '\0') return 0;
188     int c = 0;
189     while (b_aux != NULL) {
190         c++;
191         b_aux = b_aux->pnext;
192     }
193     return c;
194 }
195 
196 /**
197 * \brief Get printable buffer length (excluded special chars)
198 *
199 * \details Get printable bufferlength, which excludes special characters
200 * as they should never be printed to a screen.
201 *
202 * \param[in] buf
203 *
204 * \return c printable buffer length
205 */
206 
get_pbuflen(struct block * buf)207 int get_pbuflen(struct block * buf) {
208     struct block * b_aux = buf;
209     if (b_aux == NULL || b_aux->value == '\0') return 0;
210     int c = 0;
211     while (b_aux != NULL) {
212         if ( !is_idchar(b_aux->value) ) c++;
213         b_aux = b_aux->pnext;
214     }
215     return c;
216 }
217 
218 /**
219 * \brief Return the int value of n block
220 *
221 * \param[in] buf
222 * \param[in] d
223 *
224 * \return none
225 */
226 
get_bufval(struct block * buf,int d)227 int get_bufval(struct block * buf, int d) {
228     int i;
229     struct block * b_aux = buf;
230     for (i = 0; i < d; i++) {
231         b_aux = b_aux->pnext;
232     }
233     return b_aux->value;
234 }
235 
236 /**
237 * \brief Return an int value if found in a buffer
238 *
239 * \details Search a buffer for a given integer value.
240 *
241 * \return 0 if not found, 1 if found
242 */
243 
find_val(struct block * buf,int value)244 int find_val(struct block * buf, int value) {
245     struct block * b_aux = buf;
246     while ( b_aux != NULL && b_aux->value != '\0' ) {
247         if (b_aux->value == value) return 1;
248         b_aux = b_aux->pnext;
249     }
250     return 0;
251 }
252 
253 /**
254 * \brief Delete the first element in a buffer
255 *
256 * \param[in] buf
257 *
258 * \return none
259 */
260 
dequeue(struct block * buf)261 struct block * dequeue (struct block * buf) {
262     if (buf == NULL) return buf;
263     struct block * sig;
264     if (buf->value == '\0') return buf;
265 
266     if (buf->pnext == NULL) {
267        buf->value = '\0';
268     } else {
269         sig = buf->pnext;
270         //free(buf);
271         buf = sig;
272     }
273     return buf;
274 }
275