xref: /minix/minix/fs/procfs/buf.c (revision 83133719)
1 /* ProcFS - buf.c - by Alen Stojanov and David van Moolenbroek */
2 
3 #include "inc.h"
4 #include <stdarg.h>
5 
6 #define BUF_SIZE 4096
7 
8 static char buf[BUF_SIZE + 1];
9 static size_t off, left, used;
10 static off_t skip;
11 
12 /*===========================================================================*
13  *				buf_init				     *
14  *===========================================================================*/
15 void buf_init(off_t start, size_t len)
16 {
17 	/* Initialize the buffer for fresh use. The first 'start' bytes of the
18 	 * produced output are to be skipped. After that, up to a total of
19 	 * 'len' bytes are requested.
20 	 */
21 
22 	skip = start;
23 	left = MIN(len, BUF_SIZE);
24 	off = 0;
25 	used = 0;
26 }
27 
28 /*===========================================================================*
29  *				buf_printf				     *
30  *===========================================================================*/
31 void buf_printf(char *fmt, ...)
32 {
33 	/* Add formatted text to the end of the buffer.
34 	 */
35 	va_list args;
36 	ssize_t len, max;
37 
38 	if (left == 0)
39 		return;
40 
41 	/* There is no way to estimate how much space the result will take, so
42 	 * we need to produce the string even when skipping part of the start.
43 	 * If part of the result is to be skipped, do not memcpy; instead, save
44 	 * the offset of where the result starts within the buffer.
45 	 *
46 	 * The null terminating character is not part of the result, so room
47 	 * must be given for it to be stored after completely filling up the
48 	 * requested part of the buffer.
49 	 */
50 	max = MIN(skip + left, BUF_SIZE);
51 
52 	va_start(args, fmt);
53 	len = vsnprintf(&buf[off + used], max + 1, fmt, args);
54 	va_end(args);
55 
56 	if (skip > 0) {
57 		assert(off == 0);
58 		assert(used == 0);
59 
60 		if (skip >= len) {
61 			skip -= len;
62 
63 			return;
64 		}
65 
66 		off = skip;
67 		if (left > BUF_SIZE - off)
68 			left = BUF_SIZE - off;
69 		len -= off;
70 		skip = 0;
71 	}
72 
73 	assert(skip == 0);
74 	assert(len >= 0);
75 	assert((long) left >= 0);
76 
77 	if (len > (ssize_t) left)
78 		len = left;
79 
80 	used += len;
81 	left -= len;
82 }
83 
84 /*===========================================================================*
85  *				buf_append				     *
86  *===========================================================================*/
87 void buf_append(char *data, size_t len)
88 {
89 	/* Add arbitrary data to the end of the buffer.
90 	 */
91 
92 	if (left == 0)
93 		return;
94 
95 	if (skip > 0) {
96 		if (skip >= (ssize_t) len) {
97 			skip -= len;
98 
99 			return;
100 		}
101 
102 		data += skip;
103 		len -= skip;
104 		skip = 0;
105 	}
106 
107 	if (len > left)
108 		len = left;
109 
110 	memcpy(&buf[off + used], data, len);
111 
112 	used += len;
113 	left -= len;
114 }
115 
116 /*===========================================================================*
117  *				buf_get					     *
118  *===========================================================================*/
119 size_t buf_get(char **ptr)
120 {
121 	/* Return the buffer's starting address and the length of the used
122 	 * part, not counting the trailing null character for the latter.
123 	 */
124 
125 	*ptr = &buf[off];
126 
127 	return used;
128 }
129