]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/make/buf.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.bin / make / buf.c
1 /*-
2  * Copyright (c) 2005 Max Okumoto
3  * Copyright (c) 1988, 1989, 1990, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  * Copyright (c) 1988, 1989 by Adam de Boor
6  * Copyright (c) 1989 by Berkeley Softworks
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Adam de Boor.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by the University of
23  *      California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * @(#)buf.c    8.1 (Berkeley) 6/6/93
41  */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 /*
47  * buf.c
48  *      Functions for automatically-expanded buffers.
49  */
50
51 #include <string.h>
52 #include <stdlib.h>
53
54 #include "buf.h"
55 #include "util.h"
56
57 /**
58  * Returns the number of bytes in the buffer.  Doesn't include the
59  * null-terminating byte.
60  */
61 size_t
62 Buf_Size(const Buffer *buf)
63 {
64
65         return (buf->end - buf->buf);
66 }
67
68 /**
69  * Returns a reference to the data contained in the buffer.
70  *  
71  * @note Adding data to the Buffer object may invalidate the reference.
72  */
73 char *
74 Buf_Data(const Buffer *bp)
75 {
76
77         return (bp->buf);
78 }
79
80 /**
81  * Expand the buffer to hold the number of additional bytes, plus
82  * space to store a terminating NULL byte.
83  */
84 static inline void
85 BufExpand(Buffer *bp, size_t nb)
86 {
87         size_t  len = Buf_Size(bp);
88         size_t  size;
89
90         if (bp->size < len + nb + 1) {
91                 size = bp->size + MAX(nb + 1, BUF_ADD_INC);
92                 bp->size = size;
93                 bp->buf = erealloc(bp->buf, size);
94                 bp->end = bp->buf + len;
95         }
96 }
97
98 /**
99  * Add a single byte to the buffer.
100  */
101 void
102 Buf_AddByte(Buffer *bp, Byte byte)
103 {
104
105         BufExpand(bp, 1);
106
107         *bp->end = byte;
108         bp->end++;
109         *bp->end = '\0';
110 }
111
112 /**
113  * Add bytes to the buffer.
114  */
115 void
116 Buf_AddBytes(Buffer *bp, size_t len, const Byte *bytes)
117 {
118
119         BufExpand(bp, len);
120
121         memcpy(bp->end, bytes, len);
122         bp->end += len;
123         *bp->end = '\0';
124 }
125
126 /**
127  * Get a reference to the internal buffer.
128  *
129  * len:
130  *      Pointer to where we return the number of bytes in the internal buffer.
131  *
132  * Returns:
133  *      return A pointer to the data.
134  */
135 Byte *
136 Buf_GetAll(Buffer *bp, size_t *len)
137 {
138
139         if (len != NULL)
140                 *len = Buf_Size(bp);
141
142         return (bp->buf);
143 }
144
145 /**
146  * Get the contents of a buffer and destroy the buffer. If the buffer
147  * is NULL, return NULL.
148  *
149  * Returns:
150  *      the pointer to the data.
151  */
152 char *
153 Buf_Peel(Buffer *bp)
154 {
155         char *ret;
156
157         if (bp == NULL)
158                 return (NULL);
159         ret = bp->buf;
160         free(bp);
161         return (ret);
162 }
163
164 /**
165  * Initialize a buffer. If no initial size is given, a reasonable
166  * default is used.
167  *
168  * Returns:
169  *      A buffer object to be given to other functions in this library.
170  *
171  * Side Effects:
172  *      Space is allocated for the Buffer object and a internal buffer.
173  */
174 Buffer *
175 Buf_Init(size_t size)
176 {
177         Buffer *bp;     /* New Buffer */
178
179         if (size <= 0)
180                 size = BUF_DEF_SIZE;
181
182         bp = emalloc(sizeof(*bp));
183         bp->size = size;
184         bp->buf = emalloc(size);
185         bp->end = bp->buf;
186         *bp->end = '\0';
187
188         return (bp);
189 }
190
191 /**
192  * Destroy a buffer, and optionally free its data, too.
193  *
194  * Side Effects:
195  *      Space for the Buffer object and possibly the internal buffer
196  *      is de-allocated.
197  */
198 void
199 Buf_Destroy(Buffer *buf, Boolean freeData)
200 {
201
202         if (freeData)
203                 free(buf->buf);
204         free(buf);
205 }
206
207 /**
208  * Replace the last byte in a buffer.  If the buffer was empty
209  * intially, then a new byte will be added.
210  */
211 void
212 Buf_ReplaceLastByte(Buffer *bp, Byte byte)
213 {
214
215         if (bp->end == bp->buf) {
216                 Buf_AddByte(bp, byte);
217         } else {
218                 *(bp->end - 1) = byte;
219         }
220 }
221
222 /**
223  * Append characters in str to Buffer object
224  */
225 void
226 Buf_Append(Buffer *bp, const char str[])
227 {
228
229         Buf_AddBytes(bp, strlen(str), str);
230 }
231
232 /**
233  * Append characters in buf to Buffer object
234  */
235 void
236 Buf_AppendBuf(Buffer *bp, const Buffer *buf)
237 {
238
239         Buf_AddBytes(bp, Buf_Size(buf), buf->buf);
240 }
241
242 /**
243  * Append characters between str and end to Buffer object.
244  */
245 void
246 Buf_AppendRange(Buffer *bp, const char str[], const char *end)
247 {
248
249         Buf_AddBytes(bp, end - str, str);
250 }
251
252 /**
253  * Convert newlines in buffer to spaces.  The trailing newline is
254  * removed.
255  */
256 void
257 Buf_StripNewlines(Buffer *bp)
258 {
259         char *ptr = bp->end;
260
261         /*
262          * If there is anything in the buffer, remove the last
263          * newline character.
264          */
265         if (ptr != bp->buf) {
266                 if (*(ptr - 1) == '\n') {
267                         /* shorten buffer */
268                         *(ptr - 1) = '\0';
269                         --bp->end;
270                 }
271                 --ptr;
272         }
273
274         /* Convert newline characters to a space characters.  */
275         while (ptr != bp->buf) {
276                 if (*ptr == '\n') {
277                         *ptr = ' ';
278                 }
279                 --ptr;
280         }
281 }
282 /**
283  * Clear the contents of the buffer.
284  */
285 void
286 Buf_Clear(Buffer *bp)
287 {
288
289         bp->end = bp->buf;
290         *bp->end = '\0';
291 }