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