libisdn
|
00001 /* 00002 * 00003 * 00004 */ 00005 #ifdef HAVE_CONFIG_H 00006 #include "config.h" 00007 #endif 00008 00009 #include <stdint.h> 00010 #include <stdlib.h> 00011 #include <string.h> 00012 00013 #include "msgb.h" 00014 00015 enum { 00016 MSGBF_NONE = 0, 00017 MSGBF_BUFFER_OWNED = (1 << 0), 00018 }; 00019 00020 /******************************************************************************* 00021 * Buffer initialization / destruction 00022 *******************************************************************************/ 00023 00024 static inline int _msgb_init(struct msgb *msgb, const uint8_t *buf, const int size, const int flags) 00025 { 00026 if (!msgb || size <= 0) 00027 return -1; 00028 00029 if (flags & MSGBF_BUFFER_OWNED) { 00030 memset(msgb, 0, sizeof(*msgb) + size); 00031 msgb->buf = (uint8_t *)((uintptr_t)msgb + sizeof(*msgb)); 00032 } else if (buf) { 00033 memset(msgb, 0, sizeof(*msgb)); 00034 msgb->buf = (uint8_t *)buf; 00035 } else { 00036 return -1; 00037 } 00038 00039 msgb->flags = flags; 00040 msgb->size = size; 00041 msgb->next = NULL; 00042 return 0; 00043 } 00044 00045 int msgb_init(struct msgb *msgb, const uint8_t *buf, const int size) 00046 { 00047 return _msgb_init(msgb, buf, size, MSGBF_NONE); 00048 } 00049 00050 struct msgb *msgb_alloc(const int size) 00051 { 00052 struct msgb *msgb = NULL; 00053 00054 if (size <= 0) 00055 return NULL; 00056 00057 msgb = malloc(sizeof(*msgb) + size); 00058 if (!msgb) 00059 return NULL; 00060 00061 if (_msgb_init(msgb, NULL, size, MSGBF_BUFFER_OWNED) < 0) { 00062 free(msgb); 00063 return NULL; 00064 } 00065 00066 return msgb; 00067 } 00068 00069 struct msgb *msgb_alloc_reserve(const int size, const int reserve) 00070 { 00071 struct msgb *msgb = NULL; 00072 00073 if (size <= 0 || reserve <= 0 || size <= reserve) 00074 return NULL; 00075 00076 msgb = msgb_alloc(size); 00077 if (!msgb) 00078 return NULL; 00079 00080 if (msgb_reserve(msgb, reserve) < 0) { 00081 free(msgb); 00082 return NULL; 00083 } 00084 00085 return msgb; 00086 } 00087 00088 int msgb_destroy(struct msgb *msgb) 00089 { 00090 if (!msgb) 00091 return -1; 00092 for (struct msgb *cur = msgb, *next = NULL; cur; cur = next) { 00093 next = cur->next; 00094 /* clear content on exit */ 00095 memset(cur->buf, 0, cur->size); 00096 free(cur); 00097 } 00098 return 0; 00099 } 00100 00101 /******************************************************************************* 00102 * Buffer status 00103 *******************************************************************************/ 00104 00105 int msgb_size(const struct msgb *msgb) 00106 { 00107 return (msgb && msgb->buf) ? msgb->size : -1; 00108 } 00109 00110 int msgb_length(const struct msgb *msgb) 00111 { 00112 if (!msgb || !msgb->size || !msgb->buf) 00113 return -1; 00114 00115 return (msgb->end - msgb->head); 00116 } 00117 00118 int msgb_space(const struct msgb *msgb) 00119 { 00120 if (!msgb || !msgb->size || !msgb->buf) 00121 return -1; 00122 00123 return (msgb->size - msgb->tail); 00124 } 00125 00126 int msgb_reserved_space(const struct msgb *msgb) 00127 { 00128 if (!msgb || !msgb->size || !msgb->buf) 00129 return -1; 00130 00131 return msgb->head; 00132 } 00133 00134 int msgb_empty(const struct msgb *msgb) 00135 { 00136 if (!msgb || !msgb->size || !msgb->buf) 00137 return 0; 00138 00139 return msgb->end == msgb->head; 00140 } 00141 00142 int msgb_full(const struct msgb *msgb) 00143 { 00144 if (!msgb || !msgb->size || !msgb->buf) 00145 return 1; 00146 00147 return msgb->end == msgb->size; 00148 } 00149 00150 int msgb_left(const struct msgb *msgb) 00151 { 00152 if (!msgb || !msgb->size || !msgb->buf) 00153 return -1; 00154 00155 return (msgb->end - msgb->tail); 00156 } 00157 00158 int msgb_tell(const struct msgb *msgb) 00159 { 00160 if (!msgb || !msgb->size || !msgb->buf) 00161 return -1; 00162 00163 return (msgb->tail - msgb->head); 00164 } 00165 00166 uint8_t *msgb_head_ptr(const struct msgb *msgb) 00167 { 00168 if (!msgb || !msgb->size || !msgb->buf) 00169 return NULL; 00170 00171 return &msgb->buf[msgb->head]; 00172 } 00173 00174 uint8_t *msgb_tail_ptr(const struct msgb *msgb) 00175 { 00176 if (!msgb || !msgb->size || !msgb->buf) 00177 return NULL; 00178 00179 return &msgb->buf[msgb->tail]; 00180 } 00181 00182 00183 /******************************************************************************* 00184 * Buffer manipulation 00185 *******************************************************************************/ 00186 00187 int msgb_reserve(struct msgb *msgb, const int reserve) 00188 { 00189 if (!msgb || msgb->size <= 0 || reserve <= 0) 00190 return -1; 00191 if (msgb->head + reserve >= msgb->size) 00192 return -1; 00193 /* move head */ 00194 msgb->head += reserve; 00195 /* check if tail is still after head (update if it's not) */ 00196 if (msgb->tail < msgb->head) 00197 msgb->tail = msgb->head; 00198 /* check if data end is still after head (update if it's not) */ 00199 if (msgb->end < msgb->head) 00200 msgb->end = msgb->head; 00201 return 0; 00202 } 00203 00204 int msgb_unreserve(struct msgb *msgb, const int size) 00205 { 00206 int old_pos; 00207 00208 if (!msgb || msgb->size <= 0) 00209 return -1; 00210 00211 old_pos = msgb->head; 00212 00213 if (size <= 0) { 00214 msgb->head = 0; 00215 } else if (msgb->head >= size) { 00216 msgb->head -= size; 00217 } else { 00218 /* invalid number of bytes */ 00219 return -1; 00220 } 00221 00222 /* 00223 * Move tail and end pointer only 00224 * if they pointed to the old head position 00225 * (i.e. nothing has been read or written yet) 00226 */ 00227 if (msgb->tail == old_pos) 00228 msgb->tail = msgb->head; 00229 if (msgb->end == old_pos) 00230 msgb->end = msgb->head; 00231 return 0; 00232 } 00233 00234 int msgb_rewind(struct msgb *msgb) 00235 { 00236 if (!msgb || !msgb->buf) 00237 return -1; 00238 msgb->tail = msgb->head; 00239 return 0; 00240 } 00241 00242 int msgb_seek(struct msgb *msgb, const msgb_seek_t type, const int offset) 00243 { 00244 unsigned int pos = 0; 00245 00246 if (!msgb || !msgb->buf) 00247 return -1; 00248 00249 switch (type) { 00250 case MSGB_SEEK_CUR: 00251 pos = msgb->tail + offset; 00252 break; 00253 case MSGB_SEEK_SET: 00254 pos = msgb->head + offset; 00255 break; 00256 case MSGB_SEEK_END: 00257 pos = msgb->end - offset; 00258 break; 00259 default: 00260 return -1; 00261 } 00262 00263 if (pos < msgb->head || pos > msgb->end) 00264 return -1; 00265 00266 msgb->tail = pos; 00267 return 0; 00268 } 00269 00270 int msgb_clear(struct msgb *msgb) 00271 { 00272 if (!msgb || !msgb->buf) 00273 return -1; 00274 memset(msgb->buf, 0, msgb->size); 00275 msgb->end = msgb->tail = msgb->head; 00276 return 0; 00277 } 00278 00279 int msgb_reset(struct msgb *msgb) 00280 { 00281 if (!msgb || !msgb->buf) 00282 return -1; 00283 memset(msgb->buf, 0, msgb->size); 00284 msgb->end = msgb->tail = msgb->head = 0; 00285 return 0; 00286 } 00287 00288 /******************************************************************************* 00289 * Buffer accessors 00290 *******************************************************************************/ 00291 00292 uint8_t *msgb_put(struct msgb *msgb, const int size) 00293 { 00294 uint8_t *tmp = NULL; 00295 00296 if (!msgb || !msgb->size || !msgb->buf || size < 0) 00297 return NULL; 00298 if ((msgb->tail + size) > msgb->size) 00299 return NULL; 00300 00301 tmp = &msgb->buf[msgb->tail]; 00302 msgb->tail += size; 00303 msgb->end = MAX(msgb->end, msgb->tail); 00304 return tmp; 00305 } 00306 00307 uint8_t *msgb_get(struct msgb *msgb, const int size) 00308 { 00309 uint8_t *tmp = NULL; 00310 00311 if (!msgb || !msgb->size || !msgb->buf || size < 0) 00312 return NULL; 00313 if ((msgb->tail + size) > msgb->end) 00314 return NULL; 00315 00316 tmp = &msgb->buf[msgb->tail]; 00317 msgb->tail += size; 00318 return tmp; 00319 } 00320 00321 int msgb_write(struct msgb *msgb, const void *buf, const int size) 00322 { 00323 uint8_t *tmp = NULL; 00324 int bytes = size, ret; 00325 00326 if (!msgb || !buf || size <= 0) 00327 return -1; 00328 if ((ret = msgb_space(msgb)) < size) 00329 bytes = ret; 00330 if (bytes <= 0) 00331 return -1; 00332 if ((tmp = msgb_put(msgb, bytes)) == NULL) 00333 return -1; 00334 00335 memcpy(tmp, buf, bytes); 00336 return bytes; 00337 } 00338 00339 int msgb_read(struct msgb *msgb, void *buf, const int size) 00340 { 00341 uint8_t *tmp = NULL; 00342 int bytes = size, ret; 00343 00344 if (!msgb || !buf || size <= 0) 00345 return -1; 00346 if ((ret = msgb_left(msgb)) < size) 00347 bytes = ret; 00348 if ((tmp = msgb_get(msgb, bytes)) == NULL) 00349 return -1; 00350 00351 memcpy(buf, tmp, bytes); 00352 return bytes; 00353 } 00354 00355 int msgb_fill(struct msgb *msgb, const int c, const int size) 00356 { 00357 uint8_t *tmp = NULL; 00358 int bytes = size, ret; 00359 00360 if (!msgb || size <= 0) 00361 return -1; 00362 if ((ret = msgb_space(msgb)) < size) 00363 bytes = ret; 00364 if (bytes <= 0) 00365 return -1; 00366 if ((tmp = msgb_put(msgb, bytes)) == NULL) 00367 return -1; 00368 memset(tmp, c, bytes); 00369 return bytes; 00370 } 00371 00372 /******************************************************************************* 00373 * Buffer list accessors 00374 *******************************************************************************/ 00375 00376 00377 /******************************************************************************* 00378 * Buffer chaining 00379 *******************************************************************************/ 00380 00381 int msgb_chain_append(struct msgb *chain, struct msgb *msgb) 00382 { 00383 if (!chain || !msgb) 00384 return -1; 00385 for (struct msgb *cur = chain; cur; cur = cur->next) { 00386 if (!cur->next) { 00387 cur->next = msgb; 00388 return 0; 00389 } 00390 } 00391 return -1; 00392 } 00393 00394 struct msgb *msgb_chain_split(struct msgb *chain, struct msgb *where) 00395 { 00396 if (!chain || !where) 00397 return NULL; 00398 if (chain == where) 00399 return chain; 00400 /* find point to split */ 00401 for (struct msgb *cur = chain; cur; cur = cur->next) { 00402 if (cur->next == where) { 00403 cur->next = NULL; 00404 return where; 00405 } 00406 } 00407 return NULL; 00408 } 00409 00410 struct msgb *msgb_chain_split_at(struct msgb *chain, const int pos) 00411 { 00412 int idx = 0; 00413 if (!chain || pos < 0) 00414 return NULL; 00415 if (pos == 0) 00416 return chain; 00417 /* find point to split */ 00418 for (struct msgb *cur = chain; cur; cur = cur->next) { 00419 if (++idx == pos) { 00420 struct msgb *tmp = cur->next; 00421 cur->next = NULL; 00422 return tmp; 00423 } 00424 } 00425 return NULL; 00426 } 00427 00428 00429 /* */ 00430 static int _msgb_chain_length(const struct msgb *msgb) 00431 { 00432 int bytes = 0, ret; 00433 00434 if (!msgb) 00435 return -1; 00436 for (const struct msgb *cur = msgb; cur; cur = cur->next) { 00437 if ((ret = msgb_length(cur)) < 0) 00438 return -1; 00439 bytes += ret; 00440 } 00441 return bytes; 00442 } 00443 00444 /* */ 00445 static int _msgb_chain_size(const struct msgb *msgb) 00446 { 00447 int bytes = 0, ret; 00448 00449 if (!msgb) 00450 return -1; 00451 for (const struct msgb *cur = msgb; cur; cur = cur->next) { 00452 if ((ret = msgb_size(cur)) < 0) 00453 return -1; 00454 bytes += ret; 00455 } 00456 return bytes; 00457 } 00458 00459 static struct msgb* _msgb_linearize(struct msgb *msgb, const int reserve) 00460 { 00461 struct msgb *tmp = NULL; 00462 int size; 00463 00464 if (!msgb || reserve < 0) 00465 return NULL; 00466 if ((size = _msgb_chain_length(msgb)) <= 0) 00467 return NULL; 00468 00469 if ((tmp = (reserve) ? msgb_alloc_reserve(size + reserve, reserve) : msgb_alloc(size)) == NULL) 00470 return NULL; 00471 00472 for (struct msgb *cur = msgb; cur; cur = cur->next) { 00473 if ((size = msgb_length(cur)) <= 0) 00474 goto error; 00475 if (msgb_write(tmp, msgb_head_ptr(cur), size) < 0) 00476 goto error; 00477 } 00478 return tmp; 00479 error: 00480 msgb_destroy(tmp); 00481 return NULL; 00482 } 00483 00484 struct msgb *msgb_linearize(struct msgb *msgb) 00485 { 00486 return _msgb_linearize(msgb, 0); 00487 } 00488 00489 struct msgb *msgb_linearize_reserve(struct msgb *msgb, const int reserve) 00490 { 00491 return _msgb_linearize(msgb, reserve); 00492 } 00493 00494 int msgb_merge(struct msgb *msgb, struct msgb *outb) 00495 { 00496 int size; 00497 00498 if (!msgb || !outb) 00499 return -1; 00500 00501 if ((size = _msgb_chain_length(msgb)) <= 0) 00502 return -1; 00503 if (size > msgb_left(outb)) 00504 return -1; 00505 00506 for (struct msgb *cur = msgb; cur; cur = cur->next) { 00507 if ((size = msgb_length(cur)) <= 0) 00508 return -1; 00509 if (msgb_write(outb, msgb_head_ptr(cur), size) < 0) 00510 return -1; 00511 } 00512 return 0; 00513 } 00514 00515 static struct msgb *_msgb_split(struct msgb *msgb, const int size, const int reserve) 00516 { 00517 struct msgb *chain = NULL; 00518 int bytes; 00519 00520 if (!msgb || size <= 0 || reserve < 0) 00521 return NULL; 00522 if (msgb_left(msgb) == 0) 00523 return NULL; 00524 /* can't split chained buffers */ 00525 if (msgb->next) 00526 return NULL; 00527 00528 while ((bytes = msgb_left(msgb)) > 0) { 00529 struct msgb *tmp = NULL; 00530 00531 if ((tmp = (reserve) ? msgb_alloc_reserve(size + reserve, reserve) : msgb_alloc(size)) == NULL) 00532 goto error; 00533 00534 bytes = MIN(size, bytes); 00535 00536 if (msgb_write(tmp, msgb_get(msgb, bytes), bytes) <= 0) 00537 goto error; 00538 00539 if (!chain) 00540 chain = tmp; 00541 else if (msgb_chain_append(chain, tmp) < 0) /* optimize later */ 00542 goto error; 00543 } 00544 return chain; 00545 error: 00546 msgb_destroy(chain); 00547 return NULL; 00548 } 00549 00550 struct msgb *msgb_split(struct msgb *msgb, const int size) 00551 { 00552 return _msgb_split(msgb, size, 0); 00553 } 00554 00555 struct msgb *msgb_split_reserve(struct msgb *msgb, const int size, const int reserve) 00556 { 00557 return _msgb_split(msgb, size, reserve); 00558 } 00559 00560 int msgb_chain_count(const struct msgb *chain) 00561 { 00562 int count = 0; 00563 00564 for (const struct msgb *cur = chain; cur; cur = cur->next) 00565 count++; 00566 return count; 00567 } 00568 00569 int msgb_chain_length(const struct msgb *chain) 00570 { 00571 return _msgb_chain_length(chain); 00572 } 00573 00574 int msgb_chain_size(const struct msgb *chain) 00575 { 00576 return _msgb_chain_size(chain); 00577 }