libisdn
msgb.c
Go to the documentation of this file.
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 }