source: mainline/uspace/lib/c/generic/adt/measured_strings.c@ 7390870

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7390870 was 7390870, checked in by Jakub Jermar <jakub@…>, 15 years ago

Move ADT's used by the networking stack to libc.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup net
30 * @{
31 */
32
33/** @file
34 * Character string with measured length implementation.
35 * @see measured_strings.h
36 */
37
38#include <adt/measured_strings.h>
39#include <malloc.h>
40#include <mem.h>
41#include <unistd.h>
42#include <errno.h>
43#include <err.h>
44#include <async.h>
45
46
47measured_string_ref measured_string_create_bulk(const char * string, size_t length){
48 measured_string_ref new;
49
50 if(length == 0){
51 while(string[length]){
52 ++ length;
53 }
54 }
55 new = (measured_string_ref) malloc(sizeof(measured_string_t) + (sizeof(char) * (length + 1)));
56 if(! new){
57 return NULL;
58 }
59 new->length = length;
60 new->value = ((char *) new) + sizeof(measured_string_t);
61 // append terminating zero explicitly - to be safe
62 memcpy(new->value, string, new->length);
63 new->value[new->length] = '\0';
64 return new;
65}
66
67measured_string_ref measured_string_copy(measured_string_ref source){
68 measured_string_ref new;
69
70 if(! source){
71 return NULL;
72 }
73 new = (measured_string_ref) malloc(sizeof(measured_string_t));
74 if(new){
75 new->value = (char *) malloc(source->length + 1);
76 if(new->value){
77 new->length = source->length;
78 memcpy(new->value, source->value, new->length);
79 new->value[new->length] = '\0';
80 return new;
81 }else{
82 free(new);
83 }
84 }
85 return NULL;
86}
87
88int measured_strings_receive(measured_string_ref * strings, char ** data, size_t count){
89 ERROR_DECLARE;
90
91 size_t * lengths;
92 size_t index;
93 size_t length;
94 char * next;
95 ipc_callid_t callid;
96
97 if((! strings) || (! data) || (count <= 0)){
98 return EINVAL;
99 }
100 lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
101 if(! lengths){
102 return ENOMEM;
103 }
104 if((! async_data_write_receive(&callid, &length))
105 || (length != sizeof(size_t) * (count + 1))){
106 free(lengths);
107 return EINVAL;
108 }
109 if(ERROR_OCCURRED(async_data_write_finalize(callid, lengths, sizeof(size_t) * (count + 1)))){
110 free(lengths);
111 return ERROR_CODE;
112 }
113 *data = malloc(lengths[count]);
114 if(!(*data)){
115 return ENOMEM;
116 }
117 (*data)[lengths[count] - 1] = '\0';
118 *strings = (measured_string_ref) malloc(sizeof(measured_string_t) * count);
119 if(!(*strings)){
120 free(lengths);
121 free(*data);
122 return ENOMEM;
123 }
124 next = * data;
125 for(index = 0; index < count; ++ index){
126 (*strings)[index].length = lengths[index];
127 if(lengths[index] > 0){
128 if((! async_data_write_receive(&callid, &length))
129 || (length != lengths[index])){
130 free(*data);
131 free(*strings);
132 free(lengths);
133 return EINVAL;
134 }
135 ERROR_PROPAGATE(async_data_write_finalize(callid, next, lengths[index]));
136 (*strings)[index].value = next;
137 next += lengths[index];
138 *next = '\0';
139 ++ next;
140 }else{
141 (*strings)[index].value = NULL;
142 }
143 }
144 free(lengths);
145 return EOK;
146}
147
148/** Computes the lengths of the measured strings in the given array.
149 * @param[in] strings The measured strings array to be processed.
150 * @param[in] count The measured strings array size.
151 * @returns The computed sizes array.
152 * @returns NULL if there is not enough memory left.
153 */
154static size_t * prepare_lengths(const measured_string_ref strings, size_t count){
155 size_t * lengths;
156 size_t index;
157 size_t length;
158
159 lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
160 if(! lengths){
161 return NULL;
162 }
163 length = 0;
164 for(index = 0; index < count; ++ index){
165 lengths[index] = strings[index].length;
166 length += lengths[index] + 1;
167 }
168 lengths[count] = length;
169 return lengths;
170}
171
172int measured_strings_reply(const measured_string_ref strings, size_t count){
173 ERROR_DECLARE;
174
175 size_t * lengths;
176 size_t index;
177 size_t length;
178 ipc_callid_t callid;
179
180 if((! strings) || (count <= 0)){
181 return EINVAL;
182 }
183 lengths = prepare_lengths(strings, count);
184 if(! lengths){
185 return ENOMEM;
186 }
187 if((! async_data_read_receive(&callid, &length))
188 || (length != sizeof(size_t) * (count + 1))){
189 free(lengths);
190 return EINVAL;
191 }
192 if(ERROR_OCCURRED(async_data_read_finalize(callid, lengths, sizeof(size_t) * (count + 1)))){
193 free(lengths);
194 return ERROR_CODE;
195 }
196 free(lengths);
197 for(index = 0; index < count; ++ index){
198 if(strings[index].length > 0){
199 if((! async_data_read_receive(&callid, &length))
200 || (length != strings[index].length)){
201 return EINVAL;
202 }
203 ERROR_PROPAGATE(async_data_read_finalize(callid, strings[index].value, strings[index].length));
204 }
205 }
206 return EOK;
207}
208
209int measured_strings_return(int phone, measured_string_ref * strings, char ** data, size_t count){
210 ERROR_DECLARE;
211
212 size_t * lengths;
213 size_t index;
214 char * next;
215
216 if((phone <= 0) || (! strings) || (! data) || (count <= 0)){
217 return EINVAL;
218 }
219 lengths = (size_t *) malloc(sizeof(size_t) * (count + 1));
220 if(! lengths){
221 return ENOMEM;
222 }
223 if(ERROR_OCCURRED(async_data_read_start(phone, lengths, sizeof(size_t) * (count + 1)))){
224 free(lengths);
225 return ERROR_CODE;
226 }
227 *data = malloc(lengths[count]);
228 if(!(*data)){
229 return ENOMEM;
230 }
231 *strings = (measured_string_ref) malloc(sizeof(measured_string_t) * count);
232 if(!(*strings)){
233 free(lengths);
234 free(*data);
235 return ENOMEM;
236 }
237 next = * data;
238 for(index = 0; index < count; ++ index){
239 (*strings)[index].length = lengths[index];
240 if(lengths[index] > 0){
241 ERROR_PROPAGATE(async_data_read_start(phone, next, lengths[index]));
242 (*strings)[index].value = next;
243 next += lengths[index];
244 *next = '\0';
245 ++ next;
246 }else{
247 (*strings)[index].value = NULL;
248 }
249 }
250 free(lengths);
251 return EOK;
252}
253
254int measured_strings_send(int phone, const measured_string_ref strings, size_t count){
255 ERROR_DECLARE;
256
257 size_t * lengths;
258 size_t index;
259
260 if((phone <= 0) || (! strings) || (count <= 0)){
261 return EINVAL;
262 }
263 lengths = prepare_lengths(strings, count);
264 if(! lengths){
265 return ENOMEM;
266 }
267 if(ERROR_OCCURRED(async_data_write_start(phone, lengths, sizeof(size_t) * (count + 1)))){
268 free(lengths);
269 return ERROR_CODE;
270 }
271 free(lengths);
272 for(index = 0; index < count; ++ index){
273 if(strings[index].length > 0){
274 ERROR_PROPAGATE(async_data_write_start(phone, strings[index].value, strings[index].length));
275 }
276 }
277 return EOK;
278}
279
280/** @}
281 */
282
Note: See TracBrowser for help on using the repository browser.