1 /******************************************************************************
2 *   This file is part of TinTin++                                             *
3 *                                                                             *
4 *   Copyright 2004-2020 Igor van den Hoven                                    *
5 *                                                                             *
6 *   TinTin++ is free software; you can redistribute it and/or modify          *
7 *   it under the terms of the GNU General Public License as published by      *
8 *   the Free Software Foundation; either version 3 of the License, or         *
9 *   (at your option) any later version.                                       *
10 *                                                                             *
11 *   This program is distributed in the hope that it will be useful,           *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
14 *   GNU General Public License for more details.                              *
15 *                                                                             *
16 *   You should have received a copy of the GNU General Public License         *
17 *   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
18 ******************************************************************************/
19 
20 /******************************************************************************
21 *                               T I N T I N + +                               *
22 *                                                                             *
23 *                      coded by Igor van den Hoven 2007                       *
24 ******************************************************************************/
25 
26 #include "tintin.h"
27 
28 struct str_data *str_alloc_list(int size);
29 
restring(char * point,char * string)30 char *restring(char *point, char *string)
31 {
32 	if (point)
33 	{
34 		free(point);
35 	}
36 
37 	return strdup(string);
38 }
39 
restringf(char * point,char * fmt,...)40 char *restringf(char *point, char *fmt, ...)
41 {
42 	char string[STRING_SIZE];
43 	va_list args;
44 
45 	va_start(args, fmt);
46 	vsprintf(string, fmt, args);
47 	va_end(args);
48 
49 	if (point)
50 	{
51 		free(point);
52 	}
53 
54 	return strdup(string);
55 }
56 
57 
58 /*
59 	str_ functions
60 */
61 
init_memory(void)62 void init_memory(void)
63 {
64 	gtd->memory            = calloc(1, sizeof(struct memory_data));
65 
66 	gtd->memory->debug     = calloc(1, sizeof(struct stack_data *));
67 
68 	gtd->memory->stack     = calloc(1, sizeof(struct str_data *));
69 	gtd->memory->stack_max = 1;
70 
71 	gtd->memory->list      = calloc(1, sizeof(struct str_data *));
72 	gtd->memory->list_max  = 1;
73 
74 	gtd->memory->free      = calloc(1, sizeof(int));
75 	gtd->memory->free_max  = 1;
76 }
77 
78 
str_ptr_alloc(int size)79 struct str_data *str_ptr_alloc(int size)
80 {
81 	return str_alloc_list(size);
82 /*
83 	struct str_data *str_ptr = (struct str_data *) calloc(1, sizeof(struct str_data) + size + 1);
84 
85 	str_ptr->max = size + 1;
86 
87 	return str_ptr;
88 */
89 }
90 
get_str_ptr(char * str)91 struct str_data *get_str_ptr(char *str)
92 {
93 	return (struct str_data *) (str - sizeof(struct str_data));
94 }
95 
get_str_str(struct str_data * str_ptr)96 char *get_str_str(struct str_data *str_ptr)
97 {
98 	return (char *) str_ptr + sizeof(struct str_data);
99 }
100 
str_ptr_realloc(struct str_data * str_ptr,int size)101 struct str_data *str_ptr_realloc(struct str_data *str_ptr, int size)
102 {
103 	if (str_ptr->max <= size)
104 	{
105 		str_ptr = (struct str_data *) realloc(str_ptr, sizeof(struct str_data) + size + 1);
106 
107 		switch (str_ptr->flags)
108 		{
109 			case STR_FLAG_STACK:
110 				gtd->memory->stack[str_ptr->index] = str_ptr;
111 				break;
112 
113 			case STR_FLAG_LIST:
114 				gtd->memory->list[str_ptr->index] = str_ptr;
115 				break;
116 
117 			default:
118 				printf("\e[1;35mstr_ptr_realloc: unknown memory type (%d)", str_ptr->flags);
119 				break;
120 		}
121 
122 		str_ptr->max = size + 1;
123 	}
124 	else
125 	{
126 		printf("\e[1;35mstr_ptr_realloc: shrink error max=%d len=%d\n", str_ptr->max, str_ptr->len);
127 	}
128 
129 	return str_ptr;
130 }
131 
132 
str_alloc(int size)133 char *str_alloc(int size)
134 {
135 	struct str_data *str_ptr;
136 
137 	str_ptr = str_ptr_alloc(size);
138 
139 	return get_str_str(str_ptr);
140 }
141 
str_ptr_resize(struct str_data * str_ptr,int add)142 struct str_data *str_ptr_resize(struct str_data *str_ptr, int add)
143 {
144 	int len = str_ptr->len;
145 
146 	if (str_ptr->max <= len + add)
147 	{
148 		str_ptr = str_ptr_realloc(str_ptr, len + add + 1);
149 	}
150 	return str_ptr;
151 }
152 
str_resize(char ** str,int add)153 char *str_resize(char **str, int add)
154 {
155 	struct str_data *str_ptr = get_str_ptr(*str);
156 
157 	str_ptr = str_ptr_resize(str_ptr, add);
158 
159 	*str = get_str_str(str_ptr);
160 
161 	return *str;
162 }
163 
164 // call after a non str_ function alters *str to set the correct length.
165 
str_fix(char * original)166 int str_fix(char *original)
167 {
168 	struct str_data *str_ptr = get_str_ptr(original);
169 
170 	str_ptr->len = strlen(original);
171 
172 	return str_ptr->len;
173 }
174 
str_len(char * str)175 int str_len(char *str)
176 {
177 	return get_str_ptr(str)->len;
178 }
179 
str_max(char * str)180 int str_max(char *str)
181 {
182 	return get_str_ptr(str)->max;
183 }
184 
185 
186 // like str_dup but return an empty string
187 
str_mim(char * original)188 char *str_mim(char *original)
189 {
190 	char *string = str_alloc(strlen(original));
191 
192 	str_cpy(&string, "");
193 
194 	return string;
195 }
196 
197 // give **clone the same max length as *original.
198 
str_clone(char ** clone,char * original)199 void str_clone(char **clone, char *original)
200 {
201 	struct str_data *clo_ptr = get_str_ptr(*clone);
202 
203 	int len = str_len(original);
204 
205 	if (clo_ptr->max < len)
206 	{
207 		clo_ptr = str_ptr_realloc(clo_ptr, len * 2);
208 
209 		*clone = get_str_str(clo_ptr);
210 	}
211 }
212 
str_dup_clone(char * original)213 char *str_dup_clone(char *original)
214 {
215 	char *dup;
216 	int len;
217 
218 	len = str_len(original);
219 
220 	dup = str_alloc(len);
221 
222 	memcpy(dup, original, len + 1);
223 
224 	get_str_ptr(dup)->len = len;
225 
226 	return dup;
227 }
228 
229 
str_dup(char * original)230 char *str_dup(char *original)
231 {
232 	char *dup;
233 
234 	if (*original == 0)
235 	{
236 		return str_alloc(0);
237 	}
238 	dup = str_alloc(strlen(original));
239 
240 	str_cpy(&dup, original);
241 
242 	return dup;
243 }
244 
str_dup_printf(char * fmt,...)245 char *str_dup_printf(char *fmt, ...)
246 {
247 	char *str, *ptv;
248 	int len;
249 	va_list args;
250 
251 	va_start(args, fmt);
252 
253 	len = vasprintf(&ptv, fmt, args);
254 
255 	va_end(args);
256 
257 	str = str_alloc(len);
258 
259 	memcpy(str, ptv, len + 1);
260 
261 	free(ptv);
262 
263 	return str;
264 }
265 
str_cpy(char ** str,char * buf)266 char *str_cpy(char **str, char *buf)
267 {
268 	int buf_len;
269 	struct str_data *str_ptr;
270 
271 	buf_len = strlen(buf);
272 
273 	str_ptr = get_str_ptr(*str);
274 
275 	if (str_ptr->max <= buf_len)
276 	{
277 		str_ptr = str_ptr_realloc(str_ptr, buf_len);
278 
279 		*str = get_str_str(str_ptr);
280 	}
281 	str_ptr->len = buf_len;
282 
283 	strcpy(*str, buf);
284 
285 	return *str;
286 }
287 
str_cpy_printf(char ** str,char * fmt,...)288 char *str_cpy_printf(char **str, char *fmt, ...)
289 {
290 	struct str_data *str_ptr;
291 	char *ptv;
292 	va_list args;
293 	int len;
294 
295 	va_start(args, fmt);
296 
297 	len = vasprintf(&ptv, fmt, args);
298 
299 	va_end(args);
300 /*
301 	str_cpy(str, ptv);
302 
303 	return *str;
304 */
305 	str_ptr = get_str_ptr(*str);
306 
307 	if (str_ptr->max <= len)
308 	{
309 		str_ptr = str_ptr_realloc(str_ptr, len);
310 
311 		*str = get_str_str(str_ptr);
312 	}
313 
314 	memcpy(*str, ptv, len + 1);
315 
316 	str_ptr->len = len;
317 
318 	free(ptv);
319 
320 	return *str;
321 }
322 
323 // unused
324 
str_ndup(char * buf,int len)325 char *str_ndup(char *buf, int len)
326 {
327 	char *dup = str_alloc(len + 1);
328 
329 	str_ncpy(&dup, buf, len);
330 
331 	return dup;
332 }
333 
334 // Like strncpy but handles the string terminator properly
335 
str_ncpy(char ** str,char * buf,int len)336 char *str_ncpy(char **str, char *buf, int len)
337 {
338 	int buf_len;
339 	struct str_data *str_ptr;
340 
341 	buf_len = strnlen(buf, len);
342 
343 	str_ptr = get_str_ptr(*str);
344 
345 	if (str_ptr->max <= buf_len)
346 	{
347 		str_ptr = str_ptr_realloc(str_ptr, len);
348 
349 		*str = get_str_str(str_ptr);
350 	}
351 
352 	str_ptr->len = UMIN(buf_len, len);
353 
354 	strncpy(*str, buf, len);
355 
356 	(*str)[len] = 0;
357 
358 	return *str;
359 }
360 
361 
str_cat_len(char ** str,char * arg,int len)362 char *str_cat_len(char **str, char *arg, int len)
363 {
364 	struct str_data *str_ptr;
365 
366 	str_ptr = get_str_ptr(*str);
367 
368 	if (str_ptr->max <= str_ptr->len + len)
369 	{
370 		str_ptr = str_ptr_resize(str_ptr, len);
371 
372 		*str = get_str_str(str_ptr);
373 	}
374 
375 	strcpy(&(*str)[str_ptr->len], arg);
376 
377 	str_ptr->len += len;
378 
379 	return *str;
380 }
381 
str_cat(char ** str,char * arg)382 char *str_cat(char **str, char *arg)
383 {
384 	return str_cat_len(str, arg, strlen(arg));
385 }
386 
str_cat_chr(char ** str,char chr)387 char *str_cat_chr(char **str, char chr)
388 {
389 	struct str_data *str_ptr;
390 
391 	str_ptr = get_str_ptr(*str);
392 
393 	if (str_ptr->max <= str_ptr->len + 1)
394 	{
395 		str_ptr = str_ptr_realloc(str_ptr, str_ptr->max + 10);
396 
397 		*str = get_str_str(str_ptr);
398 	}
399 
400 	(*str)[str_ptr->len++] = chr;
401 
402 	(*str)[str_ptr->len] = 0;
403 
404 	return *str;
405 }
406 
str_cat_printf(char ** str,char * fmt,...)407 char *str_cat_printf(char **str, char *fmt, ...)
408 {
409 	char *arg;
410 	va_list args;
411 	int len;
412 
413 	va_start(args, fmt);
414 
415 	len = vasprintf(&arg, fmt, args);
416 
417 	va_end(args);
418 
419 	str_cat_len(str, arg, len);
420 
421 	free(arg);
422 
423 	return *str;
424 }
425 
426 
str_cap(char ** str,int index,char * buf)427 char *str_cap(char **str, int index, char *buf)
428 {
429 	int buf_len;
430 	struct str_data *str_ptr;
431 
432 	buf_len = strlen(buf);
433 
434 	str_ptr = get_str_ptr(*str);
435 
436 	if (str_ptr->max <= index + buf_len)
437 	{
438 		str_ptr = str_ptr_resize(str_ptr, buf_len);
439 
440 		*str = get_str_str(str_ptr);
441 	}
442 
443 	if (index <= str_ptr->len)
444 	{
445 		strcpy(&(*str)[index], buf);
446 	}
447 	else
448 	{
449 		tintin_printf2(gtd->ses, "debug: str_cap: index=%d str_len=%d cap=%s", index, str_ptr->len, buf);
450 	}
451 
452 	str_ptr->len = index + buf_len;
453 
454 	return *str;
455 }
456 
457 
str_ins_len(char ** str,int index,char * buf,int buf_len)458 char *str_ins_len(char **str, int index, char *buf, int buf_len)
459 {
460 	struct str_data *str_ptr;
461 
462 	str_ptr = get_str_ptr(*str);
463 
464 	if (str_ptr->max <= str_ptr->len + buf_len)
465 	{
466 		str_ptr = str_ptr_resize(str_ptr, buf_len);
467 
468 		*str = get_str_str(str_ptr);
469 	}
470 
471 	if (index >= str_ptr->len)
472 	{
473 		strcpy(&(*str)[str_ptr->len], buf);
474 	}
475 	else
476 	{
477 		int cnt;
478 		char *pta, *ptz;
479 
480 		pta = &(*str)[str_ptr->len];
481 		ptz = &(*str)[str_ptr->len + buf_len];
482 
483 		for (cnt = 0 ; cnt <= str_ptr->len - index ; cnt++)
484 		{
485 			*ptz-- = *pta--;
486 		}
487 
488 		pta = &(*str)[index];
489 		ptz = buf;
490 
491 		while (*ptz)
492 		{
493 			*pta++ = *ptz++;
494 		}
495 	}
496 
497 	str_ptr->len += buf_len;
498 
499 	return *str;
500 }
501 
str_ins(char ** str,int index,char * buf)502 char *str_ins(char **str, int index, char *buf)
503 {
504 	return str_ins_len(str, index, buf, strlen(buf));
505 }
506 
str_ins_printf(char ** str,int index,char * fmt,...)507 char *str_ins_printf(char **str, int index, char *fmt, ...)
508 {
509 	int len;
510 	char *arg;
511 	va_list args;
512 
513 	va_start(args, fmt);
514 
515 	len = vasprintf(&arg, fmt, args);
516 
517 	va_end(args);
518 
519 	str_ins_len(str, index, arg, len);
520 
521 	free(arg);
522 
523 	return *str;
524 }
525 
str_mov(char ** str,int dst,int src)526 char *str_mov(char **str, int dst, int src)
527 {
528 	struct str_data *str_ptr;
529 	char *ptm;
530 
531 	if (dst >= src)
532 	{
533 		show_error(gtd->ses, LIST_COMMAND, "str_mov: dst (%d) >= src (%d)", dst, src);
534 
535 		return *str;
536 	}
537 
538 	str_ptr = get_str_ptr(*str);
539 
540 	if (src > str_ptr->len)
541 	{
542 		show_error(gtd->ses, LIST_COMMAND, "str_mov: src (%d) >= len (%d)", src, str_ptr->len);
543 
544 		return *str;
545 	}
546 
547 	ptm = &(*str)[src];
548 
549 	str_ptr->len -= (src - dst);
550 
551 	while (*ptm)
552 	{
553 		(*str)[dst++] = *ptm++;
554 	}
555 	(*str)[dst++] = 0;
556 
557 	return *str;
558 }
559 
560 
str_alloc_free(struct str_data * str_ptr)561 void str_alloc_free(struct str_data *str_ptr)
562 {
563 	if (HAS_BIT(str_ptr->flags, STR_FLAG_STACK|STR_FLAG_FREE))
564 	{
565 		tintin_printf2(gtd->ses, "\e[1;31mstr_alloc_free: trying to free invalid memory: %d", str_ptr->flags);
566 		dump_stack();
567 		return;
568 	}
569 
570 	if (gtd->memory->free_len == gtd->memory->free_max)
571 	{
572 		gtd->memory->free_max *= 2;
573 
574 		gtd->memory->free = (int *) realloc(gtd->memory->free, sizeof(int) * gtd->memory->free_max);
575 	}
576 	SET_BIT(str_ptr->flags, STR_FLAG_FREE);
577 
578 	gtd->memory->free[gtd->memory->free_len++] = str_ptr->index;
579 }
580 
str_free(char * str)581 void str_free(char *str)
582 {
583 //	free(get_str_ptr(str));
584 
585 	str_alloc_free(get_str_ptr(str));
586 }
587 
588 // stack handling
589 
str_alloc_stack(int size)590 char *str_alloc_stack(int size)
591 {
592 	struct str_data *str_ptr;
593 	char *str;
594 
595 	if (size < BUFFER_SIZE)
596 	{
597 		size = BUFFER_SIZE;
598 	}
599 
600 	if (gtd->memory->stack_len == gtd->memory->stack_cap)
601 	{
602 		gtd->memory->stack_cap++;
603 
604 		if (gtd->memory->stack_cap == gtd->memory->stack_max)
605 		{
606 			gtd->memory->stack_max *= 2;
607 
608 			gtd->memory->stack = (struct str_data **) realloc(gtd->memory->stack, sizeof(struct str_data *) * gtd->memory->stack_max);
609 		}
610 		str_ptr = (struct str_data *) calloc(1, sizeof(struct str_data) + size + 1);
611 
612 		str_ptr->max   = size + 1;
613 		str_ptr->flags = STR_FLAG_STACK;
614 		str_ptr->index = gtd->memory->stack_len++;
615 
616 		gtd->memory->stack[str_ptr->index] = str_ptr;
617 	}
618 	else
619 	{
620 		str_ptr = gtd->memory->stack[gtd->memory->stack_len++];
621 	}
622 
623 	if (str_ptr->max < size)
624 	{
625 		str_ptr = str_ptr_realloc(str_ptr, size);
626 	}
627 
628 	str_ptr->len = 0;
629 
630 	str = get_str_str(str_ptr);
631 
632 	*str = 0;
633 
634 	return str;
635 }
636 
str_alloc_list(int size)637 struct str_data *str_alloc_list(int size)
638 {
639 	struct str_data *str_ptr;
640 	char *str;
641 
642 	if (size < 0)
643 	{
644 		tintin_printf2(gtd->ses, "str_alloc_list: negative size: %d", size);
645 		dump_stack();
646 		size = BUFFER_SIZE;
647 	}
648 
649 	if (gtd->memory->free_len)
650 	{
651 		int index;
652 
653 		index = gtd->memory->free[--gtd->memory->free_len];
654 
655 		str_ptr = gtd->memory->list[index];
656 
657 		DEL_BIT(str_ptr->flags, STR_FLAG_FREE);
658 
659 		if (size >= str_ptr->max)
660 		{
661 			str_ptr = str_ptr_realloc(str_ptr, size);
662 		}
663 		str_ptr->len = 0;
664 	}
665 	else
666 	{
667 		if (gtd->memory->list_len + 1 >= gtd->memory->list_max)
668 		{
669 			gtd->memory->list_max *= 2;
670 
671 			gtd->memory->list = (struct str_data **) realloc(gtd->memory->list, sizeof(struct str_data *) * gtd->memory->list_max);
672 		}
673 		str_ptr = (struct str_data *) calloc(1, sizeof(struct str_data) + size + 1);
674 
675 		str_ptr->max   = size + 1;
676 		str_ptr->flags = STR_FLAG_LIST;
677 		str_ptr->index = gtd->memory->list_len++;
678 
679 		gtd->memory->list[str_ptr->index] = str_ptr;
680 	}
681 
682 	str = get_str_str(str_ptr);
683 
684 	*str = 0;
685 
686 	return str_ptr;
687 }
688