File: slist.c

package info (click to toggle)
rush 2.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,276 kB
  • sloc: ansic: 46,428; sh: 18,253; yacc: 881; lex: 760; makefile: 284; awk: 87; lisp: 56; sed: 24
file content (117 lines) | stat: -rw-r--r-- 2,373 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* This file is part of GNU Rush.                  
   Copyright (C) 2008-2024 Sergey Poznyakoff

   GNU Rush is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   GNU Rush is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Rush.  If not, see <http://www.gnu.org/licenses/>. */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <librush.h>
#include <xalloc.h>

struct line_list {
	struct line_list *next;
	size_t size;
	char line[1];
};

struct slist {
	struct line_list *head, *tail;
	size_t size;
};

struct line_list *
new_line_seg(const char *p, size_t len)
{
	struct line_list *lp = xmalloc(sizeof(*lp) + len);
	lp->next = NULL;
	if (p)
		memcpy(lp->line, p, len);
	lp->size = len;
	return lp;
}

void
slist_append(slist_t slist, const char *p, size_t len)
{
	struct line_list *lp = new_line_seg(p, len);
	LIST_APPEND(lp, slist->head, slist->tail);
	slist->size += len;
}

char *
slist_alloc(slist_t slist, size_t len)
{
	struct line_list *lp = new_line_seg(NULL, len);
	LIST_APPEND(lp, slist->head, slist->tail);
	slist->size += len;
	return lp->line;
}

char *
slist_reduce(slist_t slist, char **pbuf, size_t *psize)
{
	struct line_list *lp;
	size_t total = slist->size + 1;
	size_t dummy;
	char *s;

	if (!psize) {
		dummy = 0;
		psize = &dummy;
		*pbuf = NULL;
	}
	
	if (*psize < total) {
		if (!*pbuf)
			*pbuf = xmalloc(total);
		else
			*pbuf = xrealloc(*pbuf, total);
		*psize = total;
	}
	s = *pbuf;
	for (lp = slist->head; lp; ) {
		struct line_list *next = lp->next;
		memcpy(s, lp->line, lp->size);
		s += lp->size;
		free(lp);
		lp = next;
	}
	*s++ = 0;
	slist->head = slist->tail = NULL;
	slist->size = 0;
	return *pbuf;
}

slist_t
slist_create()
{
	slist_t p = xzalloc(sizeof(*p));
	return p;
}

void
slist_free(slist_t slist)
{
	struct line_list *lp;
	for (lp = slist->head; lp; ) {
		struct line_list *next = lp->next;
		free(lp);
		lp = next;
	}
	free(slist);
}