xref: /freebsd/contrib/lib9p/sbuf/sbuf.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /*
2  * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
3  * All rights reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted providing that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  * Minimal libsbuf reimplementation for Mac OS X.
30  */
31 
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include "sbuf.h"
38 
39 #define	SBUF_INITIAL_SIZE	128
40 
41 struct sbuf *
42 sbuf_new_auto()
43 {
44 	struct sbuf *s;
45 
46 	s = malloc(sizeof(struct sbuf));
47 	s->s_buf = calloc(1, SBUF_INITIAL_SIZE + 1);
48 	s->s_capacity = s->s_buf != NULL ? SBUF_INITIAL_SIZE : 0;
49 	s->s_size = 0;
50 
51 	return (s);
52 }
53 
54 int
55 sbuf_cat(struct sbuf *s, const char *str)
56 {
57 	int req = (int)strlen(str);
58 
59 	if (s->s_size + req >= s->s_capacity) {
60 		s->s_capacity = s->s_size + req + 1;
61 		s->s_buf = realloc(s->s_buf, (size_t)s->s_capacity);
62 	}
63 	if (s->s_buf == NULL)
64 		return (-1);
65 
66 	strcpy(s->s_buf + s->s_size, str);
67 	s->s_size += req;
68 
69 	return (0);
70 }
71 
72 int
73 sbuf_printf(struct sbuf *s, const char *fmt, ...)
74 {
75 	int ret;
76 	va_list ap;
77 
78 	va_start(ap, fmt);
79 	ret = sbuf_vprintf(s, fmt, ap);
80 	va_end(ap);
81 
82 	return (ret);
83 }
84 
85 int
86 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list args)
87 {
88 	va_list copy;
89 	int req;
90 
91 	va_copy(copy, args);
92 	req = vsnprintf(NULL, 0, fmt, copy);
93 	va_end(copy);
94 
95 	if (s->s_size + req >= s->s_capacity) {
96 		s->s_capacity = s->s_size + req + 1;
97 		s->s_buf = realloc(s->s_buf, (size_t)s->s_capacity);
98 	}
99 	if (s->s_buf == NULL)
100 		return (-1);
101 
102 	req = vsnprintf(s->s_buf + s->s_size, req + 1, fmt, args);
103 	s->s_size += req;
104 
105 	return (0);
106 }
107 
108 char *
109 sbuf_data(struct sbuf *s)
110 {
111 	return (s->s_buf);
112 }
113 
114 int
115 sbuf_finish(struct sbuf *s)
116 {
117 	if (s->s_buf != NULL)
118 		s->s_buf[s->s_size] = '\0';
119 	return (0);
120 }
121 
122 void
123 sbuf_delete(struct sbuf *s)
124 {
125 	free(s->s_buf);
126 	free(s);
127 }
128