Changeset edba2b6f in mainline
- Timestamp:
- 2010-09-26T13:03:18Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0402bda5
- Parents:
- 7390870
- Location:
- uspace/lib/c
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/adt/measured_strings.c
r7390870 redba2b6f 32 32 33 33 /** @file 34 * 35 * 34 * Character string with measured length implementation. 35 * @see measured_strings.h 36 36 */ 37 37 … … 44 44 #include <async.h> 45 45 46 47 measured_string_ref measured_string_create_bulk(const char * string, size_t length){ 46 /** Creates a new measured string bundled with a copy of the given string 47 * itself as one memory block. 48 * 49 * If the measured string is being freed, whole memory block is freed. 50 * The measured string should be used only as a constant. 51 * 52 * @param[in] string The initial character string to be stored. 53 * @param[in] length The length of the given string without the terminating 54 * zero ('/0') character. If the length is zero (0), the 55 * actual length is computed. The given length is used and 56 * appended with the terminating zero ('\\0') character 57 * otherwise. 58 * @returns The new bundled character string with measured length. 59 * @returns NULL if there is not enough memory left. 60 */ 61 measured_string_ref 62 measured_string_create_bulk(const char * string, size_t length) 63 { 48 64 measured_string_ref new; 49 65 50 if (length == 0){51 while (string[length]){52 ++ 53 54 }55 new = (measured_string_ref) malloc(sizeof(measured_string_t) +(sizeof(char) * (length + 1)));56 if (! new){66 if (length == 0) { 67 while (string[length]) 68 ++length; 69 } 70 new = (measured_string_ref) malloc(sizeof(measured_string_t) + 71 (sizeof(char) * (length + 1))); 72 if (!new) 57 73 return NULL; 58 } 74 59 75 new->length = length; 60 76 new->value = ((char *) new) + sizeof(measured_string_t); … … 62 78 memcpy(new->value, string, new->length); 63 79 new->value[new->length] = '\0'; 80 64 81 return new; 65 82 } 66 83 67 measured_string_ref measured_string_copy(measured_string_ref source){ 84 /** Copies the given measured string with separated header and data parts. 85 * 86 * @param[in] source The source measured string to be copied. 87 * @returns The copy of the given measured string. 88 * @returns NULL if the source parameter is NULL. 89 * @returns NULL if there is not enough memory left. 90 */ 91 measured_string_ref measured_string_copy(measured_string_ref source) 92 { 68 93 measured_string_ref new; 69 94 70 if (! source){95 if (!source) 71 96 return NULL; 72 } 97 73 98 new = (measured_string_ref) malloc(sizeof(measured_string_t)); 74 if (new){99 if (new) { 75 100 new->value = (char *) malloc(source->length + 1); 76 if (new->value){101 if (new->value) { 77 102 new->length = source->length; 78 103 memcpy(new->value, source->value, new->length); 79 104 new->value[new->length] = '\0'; 80 105 return new; 81 } else{106 } else { 82 107 free(new); 83 108 } 84 109 } 110 85 111 return NULL; 86 112 } 87 113 88 int measured_strings_receive(measured_string_ref * strings, char ** data, size_t count){ 114 /** Receives a measured strings array from a calling module. 115 * 116 * Creates the array and the data memory blocks. 117 * This method should be used only while processing IPC messages as the array 118 * size has to be negotiated in advance. 119 * 120 * @param[out] strings The received measured strings array. 121 * @param[out] data The measured strings data. This memory block stores the 122 * actual character strings. 123 * @param[in] count The size of the measured strings array. 124 * @returns EOK on success. 125 * @returns EINVAL if the strings or data parameter is NULL. 126 * @returns EINVAL if the count parameter is zero (0). 127 * @returns EINVAL if the sent array differs in size. 128 * @returns EINVAL if there is inconsistency in sent measured 129 * strings' lengths (should not occur). 130 * @returns ENOMEM if there is not enough memory left. 131 * @returns Other error codes as defined for the 132 * async_data_write_finalize() function. 133 */ 134 int 135 measured_strings_receive(measured_string_ref *strings, char **data, 136 size_t count) 137 { 89 138 ERROR_DECLARE; 90 139 91 size_t * 140 size_t *lengths; 92 141 size_t index; 93 142 size_t length; 94 char * 143 char *next; 95 144 ipc_callid_t callid; 96 145 97 if ((! strings) || (! data) || (count <= 0)){98 return EINVAL; 99 } 146 if ((!strings) || (!data) || (count <= 0)) 147 return EINVAL; 148 100 149 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)))){ 150 if (!lengths) 151 return ENOMEM; 152 153 if ((!async_data_write_receive(&callid, &length)) || 154 (length != sizeof(size_t) * (count + 1))) { 155 free(lengths); 156 return EINVAL; 157 } 158 if(ERROR_OCCURRED(async_data_write_finalize(callid, lengths, 159 sizeof(size_t) * (count + 1)))) { 110 160 free(lengths); 111 161 return ERROR_CODE; 112 162 } 113 163 *data = malloc(lengths[count]); 114 if (!(*data)){164 if (!(*data)) { 115 165 return ENOMEM; 116 166 } 117 167 (*data)[lengths[count] - 1] = '\0'; 118 *strings = (measured_string_ref) malloc(sizeof(measured_string_t) * count); 119 if(!(*strings)){ 168 169 *strings = (measured_string_ref) malloc(sizeof(measured_string_t) * 170 count); 171 if (!(*strings)) { 120 172 free(lengths); 121 173 free(*data); 122 174 return ENOMEM; 123 175 } 124 next = * data; 125 for(index = 0; index < count; ++ index){ 176 177 next = *data; 178 for (index = 0; index < count; ++index) { 126 179 (*strings)[index].length = lengths[index]; 127 if (lengths[index] > 0){128 if ((! async_data_write_receive(&callid, &length))129 || (length != lengths[index])){180 if (lengths[index] > 0) { 181 if ((!async_data_write_receive(&callid, &length)) || 182 (length != lengths[index])) { 130 183 free(*data); 131 184 free(*strings); … … 133 186 return EINVAL; 134 187 } 135 ERROR_PROPAGATE(async_data_write_finalize(callid, next, lengths[index])); 188 ERROR_PROPAGATE(async_data_write_finalize(callid, next, 189 lengths[index])); 190 (*strings)[index].value = next; 191 next += lengths[index]; 192 *next = '\0'; 193 ++next; 194 } else { 195 (*strings)[index].value = NULL; 196 } 197 } 198 199 free(lengths); 200 return EOK; 201 } 202 203 /** Computes the lengths of the measured strings in the given array. 204 * 205 * @param[in] strings The measured strings array to be processed. 206 * @param[in] count The measured strings array size. 207 * @returns The computed sizes array. 208 * @returns NULL if there is not enough memory left. 209 */ 210 static size_t *prepare_lengths(const measured_string_ref strings, size_t count) 211 { 212 size_t *lengths; 213 size_t index; 214 size_t length; 215 216 lengths = (size_t *) malloc(sizeof(size_t) * (count + 1)); 217 if (!lengths) 218 return NULL; 219 220 length = 0; 221 for (index = 0; index < count; ++ index) { 222 lengths[index] = strings[index].length; 223 length += lengths[index] + 1; 224 } 225 lengths[count] = length; 226 return lengths; 227 } 228 229 /** Replies the given measured strings array to a calling module. 230 * 231 * This method should be used only while processing IPC messages as the array 232 * size has to be negotiated in advance. 233 * 234 * @param[in] strings The measured strings array to be transferred. 235 * @param[in] count The measured strings array size. 236 * @returns EOK on success. 237 * @returns EINVAL if the strings parameter is NULL. 238 * @returns EINVAL if the count parameter is zero (0). 239 * @returns EINVAL if the calling module does not accept the given 240 * array size. 241 * @returns EINVAL if there is inconsistency in sent measured 242 * strings' lengths (should not occur). 243 * @returns Other error codes as defined for the 244 * async_data_read_finalize() function. 245 */ 246 int measured_strings_reply(const measured_string_ref strings, size_t count) 247 { 248 ERROR_DECLARE; 249 250 size_t *lengths; 251 size_t index; 252 size_t length; 253 ipc_callid_t callid; 254 255 if ((!strings) || (count <= 0)) 256 return EINVAL; 257 258 lengths = prepare_lengths(strings, count); 259 if (!lengths) 260 return ENOMEM; 261 262 if ((!async_data_read_receive(&callid, &length)) || 263 (length != sizeof(size_t) * (count + 1))) { 264 free(lengths); 265 return EINVAL; 266 } 267 if (ERROR_OCCURRED(async_data_read_finalize(callid, lengths, 268 sizeof(size_t) * (count + 1)))) { 269 free(lengths); 270 return ERROR_CODE; 271 } 272 free(lengths); 273 274 for (index = 0; index < count; ++ index) { 275 if (strings[index].length > 0) { 276 if((!async_data_read_receive(&callid, &length)) || 277 (length != strings[index].length)) { 278 return EINVAL; 279 } 280 ERROR_PROPAGATE(async_data_read_finalize(callid, 281 strings[index].value, strings[index].length)); 282 } 283 } 284 285 return EOK; 286 } 287 288 /** Receives a measured strings array from another module. 289 * 290 * Creates the array and the data memory blocks. 291 * This method should be used only following other IPC messages as the array 292 * size has to be negotiated in advance. 293 * 294 * @param[in] phone The other module phone. 295 * @param[out] strings The returned measured strings array. 296 * @param[out] data The measured strings data. This memory block stores the 297 * actual character strings. 298 * @param[in] count The size of the measured strings array. 299 * @returns EOK on success. 300 * @returns EINVAL if the strings or data parameter is NULL. 301 * @returns EINVAL if the phone or count parameter is not positive. 302 * @returns EINVAL if the sent array differs in size. 303 * @returns ENOMEM if there is not enough memory left. 304 * @returns Other error codes as defined for the 305 * async_data_read_start() function. 306 */ 307 int 308 measured_strings_return(int phone, measured_string_ref *strings, char **data, 309 size_t count) 310 { 311 ERROR_DECLARE; 312 313 size_t *lengths; 314 size_t index; 315 char *next; 316 317 if ((phone <= 0) || (!strings) || (!data) || (count <= 0)) 318 return EINVAL; 319 320 lengths = (size_t *) malloc(sizeof(size_t) * (count + 1)); 321 if (!lengths) 322 return ENOMEM; 323 324 if (ERROR_OCCURRED(async_data_read_start(phone, lengths, 325 sizeof(size_t) * (count + 1)))) { 326 free(lengths); 327 return ERROR_CODE; 328 } 329 330 *data = malloc(lengths[count]); 331 if (!(*data)) { 332 return ENOMEM; 333 } 334 335 *strings = (measured_string_ref) malloc(sizeof(measured_string_t) * 336 count); 337 if (!(*strings)) { 338 free(lengths); 339 free(*data); 340 return ENOMEM; 341 } 342 343 next = *data; 344 for (index = 0; index < count; ++ index) { 345 (*strings)[index].length = lengths[index]; 346 if (lengths[index] > 0) { 347 ERROR_PROPAGATE(async_data_read_start(phone, next, 348 lengths[index])); 136 349 (*strings)[index].value = next; 137 350 next += lengths[index]; 138 351 *next = '\0'; 139 352 ++ next; 140 } else{353 } else { 141 354 (*strings)[index].value = NULL; 142 355 } 143 356 } 357 144 358 free(lengths); 145 359 return EOK; 146 360 } 147 361 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 */ 154 static size_t * prepare_lengths(const measured_string_ref strings, size_t count){ 155 size_t * lengths; 362 /** Sends the given measured strings array to another module. 363 * 364 * This method should be used only following other IPC messages as the array 365 * size has to be negotiated in advance. 366 * 367 * @param[in] phone The other module phone. 368 * @param[in] strings The measured strings array to be transferred. 369 * @param[in] count The measured strings array size. 370 * @returns EOK on success. 371 * @returns EINVAL if the strings parameter is NULL. 372 * @returns EINVAL if the phone or count parameter is not positive. 373 * @returns Other error codes as defined for the 374 * async_data_write_start() function. 375 */ 376 int 377 measured_strings_send(int phone, const measured_string_ref strings, 378 size_t count) 379 { 380 ERROR_DECLARE; 381 382 size_t *lengths; 156 383 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 172 int 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 } 384 385 if ((phone <= 0) || (!strings) || (count <= 0)) 386 return EINVAL; 387 183 388 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)))){ 389 if (!lengths) 390 return ENOMEM; 391 392 if (ERROR_OCCURRED(async_data_write_start(phone, lengths, 393 sizeof(size_t) * (count + 1)))) { 193 394 free(lengths); 194 395 return ERROR_CODE; 195 396 } 397 196 398 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)); 399 400 for (index = 0; index < count; ++index) { 401 if (strings[index].length > 0) { 402 ERROR_PROPAGATE(async_data_write_start(phone, 403 strings[index].value, strings[index].length)); 204 404 } 205 405 } 406 206 407 return EOK; 207 408 } 208 409 209 int 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 254 int 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 410 /** @} 281 411 */ -
uspace/lib/c/include/adt/measured_strings.h
r7390870 redba2b6f 27 27 */ 28 28 29 /** @addtogroup net29 /** @addtogroup libc 30 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * Character string with measured length. 35 * The structure has been designed for serialization of character strings between modules. 34 * Character string with measured length. 35 * The structure has been designed for serialization of character strings 36 * between modules. 36 37 */ 37 38 … … 44 45 * @see measured_string 45 46 */ 46 typedef struct measured_string 47 typedef struct measured_string measured_string_t; 47 48 48 49 /** Type definition of the character string with measured length pointer. 49 50 * @see measured_string 50 51 */ 51 typedef measured_string_t * 52 typedef measured_string_t *measured_string_ref; 52 53 53 54 /** Character string with measured length. 54 * This structure has been designed for serialization of character strings between modules. 55 * 56 * This structure has been designed for serialization of character strings 57 * between modules. 55 58 */ 56 struct measured_string{ 57 /** Character string data. 58 */ 59 struct measured_string { 60 /** Character string data. */ 59 61 char * value; 60 /** Character string length. 61 */ 62 /** Character string length. */ 62 63 size_t length; 63 64 }; 64 65 65 /** Creates a new measured string bundled with a copy of the given string itself as one memory block. 66 * If the measured string is being freed, whole memory block is freed. 67 * The measured string should be used only as a constant. 68 * @param[in] string The initial character string to be stored. 69 * @param[in] length The length of the given string without the terminating zero ('/0') character. If the length is zero (0), the actual length is computed. The given length is used and appended with the terminating zero ('\\0') character otherwise. 70 * @returns The new bundled character string with measured length. 71 * @returns NULL if there is not enough memory left. 72 */ 73 extern measured_string_ref measured_string_create_bulk(const char * string, size_t length); 74 75 /** Copies the given measured string with separated header and data parts. 76 * @param[in] source The source measured string to be copied. 77 * @returns The copy of the given measured string. 78 * @returns NULL if the source parameter is NULL. 79 * @returns NULL if there is not enough memory left. 80 */ 81 extern measured_string_ref measured_string_copy(measured_string_ref source); 82 83 /** Receives a measured strings array from a calling module. 84 * Creates the array and the data memory blocks. 85 * This method should be used only while processing IPC messages as the array size has to be negotiated in advance. 86 * @param[out] strings The received measured strings array. 87 * @param[out] data The measured strings data. This memory block stores the actual character strings. 88 * @param[in] count The size of the measured strings array. 89 * @returns EOK on success. 90 * @returns EINVAL if the strings or data parameter is NULL. 91 * @returns EINVAL if the count parameter is zero (0). 92 * @returns EINVAL if the sent array differs in size. 93 * @returns EINVAL if there is inconsistency in sent measured strings' lengths (should not occur). 94 * @returns ENOMEM if there is not enough memory left. 95 * @returns Other error codes as defined for the async_data_write_finalize() function. 96 */ 97 extern int measured_strings_receive(measured_string_ref * strings, char ** data, size_t count); 98 99 /** Replies the given measured strings array to a calling module. 100 * This method should be used only while processing IPC messages as the array size has to be negotiated in advance. 101 * @param[in] strings The measured strings array to be transferred. 102 * @param[in] count The measured strings array size. 103 * @returns EOK on success. 104 * @returns EINVAL if the strings parameter is NULL. 105 * @returns EINVAL if the count parameter is zero (0). 106 * @returns EINVAL if the calling module does not accept the given array size. 107 * @returns EINVAL if there is inconsistency in sent measured strings' lengths (should not occur). 108 * @returns Other error codes as defined for the async_data_read_finalize() function. 109 */ 110 extern int measured_strings_reply(const measured_string_ref strings, size_t count); 111 112 /** Receives a measured strings array from another module. 113 * Creates the array and the data memory blocks. 114 * This method should be used only following other IPC messages as the array size has to be negotiated in advance. 115 * @param[in] phone The other module phone. 116 * @param[out] strings The returned measured strings array. 117 * @param[out] data The measured strings data. This memory block stores the actual character strings. 118 * @param[in] count The size of the measured strings array. 119 * @returns EOK on success. 120 * @returns EINVAL if the strings or data parameter is NULL. 121 * @returns EINVAL if the phone or count parameter is not positive (<=0). 122 * @returns EINVAL if the sent array differs in size. 123 * @returns ENOMEM if there is not enough memory left. 124 * @returns Other error codes as defined for the async_data_read_start() function. 125 */ 126 extern int measured_strings_return(int phone, measured_string_ref * strings, char ** data, size_t count); 127 128 /** Sends the given measured strings array to another module. 129 * This method should be used only following other IPC messages as the array size has to be negotiated in advance. 130 * @param[in] phone The other module phone. 131 * @param[in] strings The measured strings array to be transferred. 132 * @param[in] count The measured strings array size. 133 * @returns EOK on success. 134 * @returns EINVAL if the strings parameter is NULL. 135 * @returns EINVAL if the phone or count parameter is not positive (<=0). 136 * @returns Other error codes as defined for the async_data_write_start() function. 137 */ 138 extern int measured_strings_send(int phone, const measured_string_ref strings, size_t count); 66 extern measured_string_ref measured_string_create_bulk(const char *, size_t); 67 extern measured_string_ref measured_string_copy(measured_string_ref); 68 extern int measured_strings_receive(measured_string_ref *, char **, size_t); 69 extern int measured_strings_reply(const measured_string_ref, size_t); 70 extern int measured_strings_return(int, measured_string_ref *, char **, size_t); 71 extern int measured_strings_send(int, const measured_string_ref, size_t); 139 72 140 73 #endif … … 142 75 /** @} 143 76 */ 144
Note:
See TracChangeset
for help on using the changeset viewer.