1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Jason King.
  14  * Copyright 2017 Joyent, Inc.
  15  */
  16 #include <sys/debug.h>
  17 #include <string.h>
  18 #include <umem.h>
  19 #include "buf.h"
  20 
  21 static inline boolean_t
  22 eof_check(buf_t *buf, size_t len)
  23 {
  24         if (buf_eof(buf))
  25                 return (B_TRUE);
  26         if (buf->b_ptr + len > buf->b_buf + buf->b_len) {
  27                 buf->b_flags |= BUF_EOF;
  28                 return (B_TRUE);
  29         }
  30         return (B_FALSE);
  31 }
  32 
  33 size_t
  34 buf_cat(buf_t *restrict dest, const buf_t *restrict src, size_t n)
  35 {
  36         size_t total = 0;
  37 
  38         BUF_IS_WRITE(dest);
  39 
  40         for (size_t i = 0; i < n; i++, src++) {
  41                 size_t amt = buf_left(src);
  42 
  43                 BUF_IS_READ(src);
  44                 if (eof_check(dest, amt))
  45                         return (total);
  46 
  47                 (void) memcpy(dest->b_ptr, src->b_ptr, amt);
  48                 dest->b_ptr += amt;
  49                 total += amt;
  50         }
  51 
  52         return (total);
  53 }
  54 
  55 size_t
  56 buf_copy(buf_t *restrict dest, const buf_t *restrict src, size_t n)
  57 {
  58         uchar_t *p = dest->b_buf;
  59         size_t total = 0;
  60 
  61         BUF_IS_WRITE(dest);
  62 
  63         dest->b_ptr = dest->b_buf;
  64         return (buf_cat(dest, src, n));
  65         for (size_t i = 0; i < n; i++) {
  66                 size_t amt = src[i].b_len;
  67 
  68                 if (total + amt > dest->b_len)
  69                         amt = dest->b_len - total;
  70                 if (amt == 0)
  71                         break;
  72 
  73                 (void) memcpy(p, src[i].b_buf, amt);
  74                 total += amt;
  75                 p += amt;
  76         }
  77 
  78 
  79         /* XXX: what to do about b_ptr? */
  80         return (total);
  81 }
  82 
  83 void
  84 buf_clear(buf_t *buf)
  85 {
  86         if (buf == NULL || buf->b_buf == NULL || buf->b_len == 0)
  87                 return;
  88 
  89         (void) memset(buf->b_buf, 0, buf->b_len);
  90         buf->b_ptr = buf->b_buf;
  91         buf->b_flags &= ~(BUF_EOF);
  92 }
  93 
  94 void
  95 buf_range(buf_t *restrict dest, buf_t *restrict src, size_t off, size_t len)
  96 {
  97         ASSERT(off + len <= src->len);
  98         dest->b_ptr = dest->b_buf = src->b_ptr + off;
  99         dest->b_len = src->b_len - off;
 100         dest->b_flags = src->b_flags & ~(BUF_ALLOCED);
 101 }
 102 
 103 boolean_t
 104 buf_alloc(buf_t *buf, size_t len)
 105 {
 106         if ((buf->b_buf = umem_zalloc(len, UMEM_DEFAULT)) == NULL)
 107                 return (B_FALSE);
 108         buf->b_ptr = buf->b_buf;
 109         buf->b_len = len;
 110         buf->b_flags = BUF_ALLOCED;
 111         return (B_TRUE);
 112 }
 113 
 114 void
 115 buf_free(buf_t *buf)
 116 {
 117         if (buf == NULL)
 118                 return;
 119 
 120         VERIFY(buf->b_flags & BUF_ALLOCED);
 121         buf_clear(buf);
 122         umem_free(buf->b_buf, buf->b_len);
 123 }
 124 
 125 int
 126 buf_cmp(const buf_t *restrict l, const buf_t *restrict r)
 127 {
 128         size_t minlen;
 129         int cmp;
 130 
 131         /* !NULL > NULL, NULL == NULL */
 132         if (r == NULL || r->b_len == 0 || r->b_ptr == NULL) {
 133                 if (l != NULL && l->b_len > 0 && l->b_ptr != NULL)
 134                         return (1);
 135                 else
 136                         return (0);
 137         }
 138 
 139         /* NULL < !NULL */
 140         if (l == NULL || l->b_len == 0 || l->b_ptr == NULL)
 141                 return (1);
 142 
 143         minlen = l->b_len;
 144         if (r->b_len < minlen)
 145                 minlen = r->b_len;
 146 
 147         cmp = memcmp(l->b_buf, r->b_buf, minlen);
 148         if (cmp != 0)
 149                 return ((cmp > 0) ? 1 : - 1);
 150 
 151         if (l->b_len > r->b_len)
 152                 return (1);
 153         if (l->b_len < r->b_len)
 154                 return (-1);
 155         return (0);
 156 }
 157 
 158 void
 159 buf_put8(buf_t *buf, uint8_t val)
 160 {
 161         BUF_IS_WRITE(buf);
 162         if (eof_check(buf, sizeof (uint8_t)))
 163                 return;
 164 
 165         *(buf->b_ptr++) = val;
 166 }
 167 
 168 void
 169 buf_put64(buf_t *buf, uint64_t val)
 170 {
 171         BUF_IS_WRITE(buf);
 172         if (eof_check(buf, sizeof (uint64_t)))
 173                 return;
 174 
 175         *(buf->b_ptr++) = (uchar_t)((val >> 56) & 0xffLL);
 176         *(buf->b_ptr++) = (uchar_t)((val >> 48) & 0xffLL);
 177         *(buf->b_ptr++) = (uchar_t)((val >> 40) & 0xffLL);
 178         *(buf->b_ptr++) = (uchar_t)((val >> 32) & 0xffLL);
 179         *(buf->b_ptr++) = (uchar_t)((val >> 24) & 0xffLL);
 180         *(buf->b_ptr++) = (uchar_t)((val >> 16) & 0xffLL);
 181         *(buf->b_ptr++) = (uchar_t)((val >> 8) & 0xffLL);
 182         *(buf->b_ptr++) = (uchar_t)(val & 0xffLL);
 183 }
 184 
 185 void
 186 buf_put32(buf_t *buf, uint32_t val)
 187 {
 188         BUF_IS_WRITE(buf);
 189         if (eof_check(buf, sizeof (uint32_t)))
 190                 return;
 191 
 192         *(buf->b_ptr++) = (uchar_t)((val >> 24) & (uint32_t)0xff);
 193         *(buf->b_ptr++) = (uchar_t)((val >> 16) & (uint32_t)0xff);
 194         *(buf->b_ptr++) = (uchar_t)((val >> 8) & (uint32_t)0xff);
 195         *(buf->b_ptr++) = (uchar_t)(val & (uint32_t)0xffLL);
 196 }
 197 
 198 extern boolean_t buf_eof(const buf_t *);
 199 extern size_t buf_left(const buf_t *);
 200 extern void buf_reset(buf_t *);
 201 extern void buf_skip(buf_t *, size_t);
 202 extern void buf_set_read(buf_t *);
 203 extern void buf_set_write(buf_t *);