Line data Source code
1 : /*
2 : Simple buffer
3 :
4 : Basic buffer manipulation routines. Taken from ELAPI code.
5 :
6 : Copyright (C) Dmitri Pal <dpal@redhat.com> 2009 - 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "config.h"
21 : #include <errno.h> /* for errors */
22 : #include <stdlib.h> /* for free() */
23 : #include <unistd.h> /* for write() */
24 : #include <string.h> /* for memcpy() */
25 :
26 : #include "simplebuffer.h"
27 : #include "trace.h"
28 :
29 : /* End line string */
30 : #define ENDLNSTR "\n"
31 :
32 : /* Function to free buffer */
33 200523 : void simplebuffer_free(struct simplebuffer *data)
34 : {
35 : TRACE_FLOW_ENTRY();
36 :
37 200523 : if (data) {
38 200523 : free(data->buffer);
39 200523 : free(data);
40 : }
41 :
42 : TRACE_FLOW_EXIT();
43 200523 : }
44 :
45 : /* Allocate buffer structure */
46 200523 : int simplebuffer_alloc(struct simplebuffer **data)
47 : {
48 200523 : int error = EOK;
49 :
50 : TRACE_FLOW_ENTRY();
51 :
52 200523 : if (!data) {
53 : TRACE_ERROR_STRING("Invalid argument", "");
54 : error = EINVAL;
55 : }
56 : else {
57 200523 : *data = (struct simplebuffer *)calloc(1,
58 : sizeof(struct simplebuffer));
59 200523 : if (*data == NULL) {
60 : TRACE_ERROR_STRING("Failed to allocate memory", "");
61 : error = ENOMEM;
62 : }
63 200523 : else error = EOK;
64 : }
65 :
66 : TRACE_FLOW_RETURN(error);
67 200523 : return error;
68 : }
69 :
70 :
71 : /* Grow buffer */
72 1477696 : int simplebuffer_grow(struct simplebuffer *data,
73 : uint32_t len,
74 : uint32_t block)
75 : {
76 1477696 : int error = EOK;
77 1477696 : unsigned char *newbuf = NULL;
78 :
79 : TRACE_FLOW_ENTRY();
80 :
81 : TRACE_INFO_NUMBER("Current length: ", data->length);
82 : TRACE_INFO_NUMBER("Current size: ", data->size);
83 : TRACE_INFO_NUMBER("Length to have: ", len);
84 : TRACE_INFO_NUMBER("Increment length: ", block);
85 :
86 : /* Grow buffer if needed */
87 3367788 : while (data->length + len >= data->size) {
88 412396 : newbuf = realloc(data->buffer, data->size + block);
89 412396 : if (newbuf == NULL) {
90 : TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
91 : return ENOMEM;
92 : }
93 412396 : data->buffer = newbuf;
94 412396 : data->size += block;
95 : TRACE_INFO_NUMBER("New size: ", data->size);
96 : }
97 :
98 : TRACE_INFO_NUMBER("Final size: ", data->size);
99 : TRACE_FLOW_RETURN(error);
100 : return error;
101 : }
102 :
103 : /* Function to add raw data to the end of the buffer.
104 : * Terminating 0 is not counted in length but appended
105 : * automatically.
106 : */
107 1212401 : int simplebuffer_add_raw(struct simplebuffer *data,
108 : void *data_in,
109 : uint32_t len,
110 : uint32_t block)
111 : {
112 :
113 1212401 : int error = EOK;
114 : uint32_t size;
115 :
116 : TRACE_FLOW_ENTRY();
117 :
118 1212401 : size = len + 1;
119 1212401 : error = simplebuffer_grow(data, size,
120 : ((block > size) ? block : size));
121 1212401 : if (error) {
122 : TRACE_ERROR_NUMBER("Failed to grow buffer.", error);
123 : return error;
124 : }
125 :
126 1212401 : memcpy(data->buffer + data->length, data_in, len);
127 1212401 : data->length += len;
128 1212401 : data->buffer[data->length] = '\0';
129 :
130 : TRACE_FLOW_EXIT();
131 1212401 : return error;
132 : }
133 :
134 : /* Function to add string to the end of the buffer. */
135 265295 : int simplebuffer_add_str(struct simplebuffer *data,
136 : const char *str,
137 : uint32_t len,
138 : uint32_t block)
139 : {
140 :
141 265295 : int error = EOK;
142 : uint32_t size;
143 :
144 : TRACE_FLOW_ENTRY();
145 :
146 265295 : size = len + 1;
147 265295 : error = simplebuffer_grow(data, size,
148 : ((block > size) ? block : size));
149 265295 : if (error) {
150 : TRACE_ERROR_NUMBER("Failed to grow buffer.", error);
151 : return error;
152 : }
153 :
154 265295 : memcpy(data->buffer + data->length, str, len);
155 265295 : data->length += len;
156 265295 : data->buffer[data->length] = '\0';
157 :
158 : TRACE_FLOW_EXIT();
159 265295 : return error;
160 : }
161 :
162 : /* Finction to add CR to the buffer */
163 496878 : int simplebuffer_add_cr(struct simplebuffer *data)
164 : {
165 496878 : int error = EOK;
166 496878 : char cr[] = ENDLNSTR;
167 :
168 : TRACE_FLOW_ENTRY();
169 :
170 496878 : error = simplebuffer_add_raw(data,
171 : (void *)cr,
172 : sizeof(ENDLNSTR) - 1,
173 : sizeof(ENDLNSTR));
174 :
175 : TRACE_FLOW_RETURN(error);
176 496878 : return error;
177 : }
178 :
179 :
180 : /* Function to write data synchroniusly */
181 307 : int simplebuffer_write(int fd, struct simplebuffer *data, uint32_t *left)
182 : {
183 : size_t res;
184 : int error;
185 :
186 : TRACE_FLOW_ENTRY();
187 :
188 : /* Write given number of bytes to the socket */
189 614 : res = write(fd,
190 307 : data->buffer + (data->length - *left),
191 307 : (size_t)(*left));
192 :
193 307 : if (res == -1) {
194 0 : error = errno;
195 : TRACE_ERROR_NUMBER("Write failed.", error);
196 0 : return error;
197 : }
198 :
199 307 : (*left) -= res;
200 :
201 : TRACE_FLOW_EXIT();
202 307 : return EOK;
203 : }
204 :
205 : /* Get buffer */
206 263652 : const unsigned char *simplebuffer_get_buf(struct simplebuffer *data)
207 : {
208 263652 : return data->buffer;
209 : }
210 :
211 : /* Get void buffer */
212 245 : void *simplebuffer_get_vbuf(struct simplebuffer *data)
213 : {
214 245 : return (void *)data->buffer;
215 : }
216 :
217 :
218 : /* Get length */
219 264503 : uint32_t simplebuffer_get_len(struct simplebuffer *data)
220 : {
221 264503 : return data->length;
222 : }
|