buffer.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2008, 2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1998-2002  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 
00022 #include <isc/buffer.h>
00023 #include <isc/mem.h>
00024 #include <isc/region.h>
00025 #include <isc/string.h>
00026 #include <isc/util.h>
00027 
00028 void
00029 isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length) {
00030         /*
00031          * Make 'b' refer to the 'length'-byte region starting at 'base'.
00032          * XXXDCL see the comment in buffer.h about base being const.
00033          */
00034 
00035         REQUIRE(b != NULL);
00036 
00037         ISC__BUFFER_INIT(b, base, length);
00038 }
00039 
00040 void
00041 isc__buffer_initnull(isc_buffer_t *b) {
00042         /*
00043          * Initialize a new buffer which has no backing store.  This can
00044          * later be grown as needed and swapped in place.
00045          */
00046 
00047         ISC__BUFFER_INIT(b, NULL, 0);
00048 }
00049 
00050 void
00051 isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
00052         /*
00053          * Re-initialize the buffer enough to reconfigure the base of the
00054          * buffer.  We will swap in the new buffer, after copying any
00055          * data we contain into the new buffer and adjusting all of our
00056          * internal pointers.
00057          *
00058          * The buffer must not be smaller than the length of the original
00059          * buffer.
00060          */
00061         REQUIRE(b->length <= length);
00062         REQUIRE(base != NULL);
00063 
00064         (void)memmove(base, b->base, b->length);
00065         b->base = base;
00066         b->length = length;
00067 }
00068 
00069 void
00070 isc__buffer_invalidate(isc_buffer_t *b) {
00071         /*
00072          * Make 'b' an invalid buffer.
00073          */
00074 
00075         REQUIRE(ISC_BUFFER_VALID(b));
00076         REQUIRE(!ISC_LINK_LINKED(b, link));
00077         REQUIRE(b->mctx == NULL);
00078 
00079         ISC__BUFFER_INVALIDATE(b);
00080 }
00081 
00082 void
00083 isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
00084         /*
00085          * Make 'r' refer to the region of 'b'.
00086          */
00087 
00088         REQUIRE(ISC_BUFFER_VALID(b));
00089         REQUIRE(r != NULL);
00090 
00091         ISC__BUFFER_REGION(b, r);
00092 }
00093 
00094 void
00095 isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
00096         /*
00097          * Make 'r' refer to the used region of 'b'.
00098          */
00099 
00100         REQUIRE(ISC_BUFFER_VALID(b));
00101         REQUIRE(r != NULL);
00102 
00103         ISC__BUFFER_USEDREGION(b, r);
00104 }
00105 
00106 void
00107 isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
00108         /*
00109          * Make 'r' refer to the available region of 'b'.
00110          */
00111 
00112         REQUIRE(ISC_BUFFER_VALID(b));
00113         REQUIRE(r != NULL);
00114 
00115         ISC__BUFFER_AVAILABLEREGION(b, r);
00116 }
00117 
00118 void
00119 isc__buffer_add(isc_buffer_t *b, unsigned int n) {
00120         /*
00121          * Increase the 'used' region of 'b' by 'n' bytes.
00122          */
00123 
00124         REQUIRE(ISC_BUFFER_VALID(b));
00125         REQUIRE(b->used + n <= b->length);
00126 
00127         ISC__BUFFER_ADD(b, n);
00128 }
00129 
00130 void
00131 isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
00132         /*
00133          * Decrease the 'used' region of 'b' by 'n' bytes.
00134          */
00135 
00136         REQUIRE(ISC_BUFFER_VALID(b));
00137         REQUIRE(b->used >= n);
00138 
00139         ISC__BUFFER_SUBTRACT(b, n);
00140 }
00141 
00142 void
00143 isc__buffer_clear(isc_buffer_t *b) {
00144         /*
00145          * Make the used region empty.
00146          */
00147 
00148         REQUIRE(ISC_BUFFER_VALID(b));
00149 
00150         ISC__BUFFER_CLEAR(b);
00151 }
00152 
00153 void
00154 isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
00155         /*
00156          * Make 'r' refer to the consumed region of 'b'.
00157          */
00158 
00159         REQUIRE(ISC_BUFFER_VALID(b));
00160         REQUIRE(r != NULL);
00161 
00162         ISC__BUFFER_CONSUMEDREGION(b, r);
00163 }
00164 
00165 void
00166 isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
00167         /*
00168          * Make 'r' refer to the remaining region of 'b'.
00169          */
00170 
00171         REQUIRE(ISC_BUFFER_VALID(b));
00172         REQUIRE(r != NULL);
00173 
00174         ISC__BUFFER_REMAININGREGION(b, r);
00175 }
00176 
00177 void
00178 isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
00179         /*
00180          * Make 'r' refer to the active region of 'b'.
00181          */
00182 
00183         REQUIRE(ISC_BUFFER_VALID(b));
00184         REQUIRE(r != NULL);
00185 
00186         ISC__BUFFER_ACTIVEREGION(b, r);
00187 }
00188 
00189 void
00190 isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
00191         /*
00192          * Sets the end of the active region 'n' bytes after current.
00193          */
00194 
00195         REQUIRE(ISC_BUFFER_VALID(b));
00196         REQUIRE(b->current + n <= b->used);
00197 
00198         ISC__BUFFER_SETACTIVE(b, n);
00199 }
00200 
00201 void
00202 isc__buffer_first(isc_buffer_t *b) {
00203         /*
00204          * Make the consumed region empty.
00205          */
00206 
00207         REQUIRE(ISC_BUFFER_VALID(b));
00208 
00209         ISC__BUFFER_FIRST(b);
00210 }
00211 
00212 void
00213 isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
00214         /*
00215          * Increase the 'consumed' region of 'b' by 'n' bytes.
00216          */
00217 
00218         REQUIRE(ISC_BUFFER_VALID(b));
00219         REQUIRE(b->current + n <= b->used);
00220 
00221         ISC__BUFFER_FORWARD(b, n);
00222 }
00223 
00224 void
00225 isc__buffer_back(isc_buffer_t *b, unsigned int n) {
00226         /*
00227          * Decrease the 'consumed' region of 'b' by 'n' bytes.
00228          */
00229 
00230         REQUIRE(ISC_BUFFER_VALID(b));
00231         REQUIRE(n <= b->current);
00232 
00233         ISC__BUFFER_BACK(b, n);
00234 }
00235 
00236 void
00237 isc_buffer_compact(isc_buffer_t *b) {
00238         unsigned int length;
00239         void *src;
00240 
00241         /*
00242          * Compact the used region by moving the remaining region so it occurs
00243          * at the start of the buffer.  The used region is shrunk by the size
00244          * of the consumed region, and the consumed region is then made empty.
00245          */
00246 
00247         REQUIRE(ISC_BUFFER_VALID(b));
00248 
00249         src = isc_buffer_current(b);
00250         length = isc_buffer_remaininglength(b);
00251         (void)memmove(b->base, src, (size_t)length);
00252 
00253         if (b->active > b->current)
00254                 b->active -= b->current;
00255         else
00256                 b->active = 0;
00257         b->current = 0;
00258         b->used = length;
00259 }
00260 
00261 isc_uint8_t
00262 isc_buffer_getuint8(isc_buffer_t *b) {
00263         unsigned char *cp;
00264         isc_uint8_t result;
00265 
00266         /*
00267          * Read an unsigned 8-bit integer from 'b' and return it.
00268          */
00269 
00270         REQUIRE(ISC_BUFFER_VALID(b));
00271         REQUIRE(b->used - b->current >= 1);
00272 
00273         cp = isc_buffer_current(b);
00274         b->current += 1;
00275         result = ((isc_uint8_t)(cp[0]));
00276 
00277         return (result);
00278 }
00279 
00280 void
00281 isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
00282         REQUIRE(ISC_BUFFER_VALID(b));
00283         REQUIRE(b->used + 1 <= b->length);
00284 
00285         ISC__BUFFER_PUTUINT8(b, val);
00286 }
00287 
00288 isc_uint16_t
00289 isc_buffer_getuint16(isc_buffer_t *b) {
00290         unsigned char *cp;
00291         isc_uint16_t result;
00292 
00293         /*
00294          * Read an unsigned 16-bit integer in network byte order from 'b',
00295          * convert it to host byte order, and return it.
00296          */
00297 
00298         REQUIRE(ISC_BUFFER_VALID(b));
00299         REQUIRE(b->used - b->current >= 2);
00300 
00301         cp = isc_buffer_current(b);
00302         b->current += 2;
00303         result = ((unsigned int)(cp[0])) << 8;
00304         result |= ((unsigned int)(cp[1]));
00305 
00306         return (result);
00307 }
00308 
00309 void
00310 isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
00311         REQUIRE(ISC_BUFFER_VALID(b));
00312         REQUIRE(b->used + 2 <= b->length);
00313 
00314         ISC__BUFFER_PUTUINT16(b, val);
00315 }
00316 
00317 void
00318 isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
00319         REQUIRE(ISC_BUFFER_VALID(b));
00320         REQUIRE(b->used + 3 <= b->length);
00321 
00322         ISC__BUFFER_PUTUINT24(b, val);
00323 }
00324 
00325 isc_uint32_t
00326 isc_buffer_getuint32(isc_buffer_t *b) {
00327         unsigned char *cp;
00328         isc_uint32_t result;
00329 
00330         /*
00331          * Read an unsigned 32-bit integer in network byte order from 'b',
00332          * convert it to host byte order, and return it.
00333          */
00334 
00335         REQUIRE(ISC_BUFFER_VALID(b));
00336         REQUIRE(b->used - b->current >= 4);
00337 
00338         cp = isc_buffer_current(b);
00339         b->current += 4;
00340         result = ((unsigned int)(cp[0])) << 24;
00341         result |= ((unsigned int)(cp[1])) << 16;
00342         result |= ((unsigned int)(cp[2])) << 8;
00343         result |= ((unsigned int)(cp[3]));
00344 
00345         return (result);
00346 }
00347 
00348 void
00349 isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
00350         REQUIRE(ISC_BUFFER_VALID(b));
00351         REQUIRE(b->used + 4 <= b->length);
00352 
00353         ISC__BUFFER_PUTUINT32(b, val);
00354 }
00355 
00356 isc_uint64_t
00357 isc_buffer_getuint48(isc_buffer_t *b) {
00358         unsigned char *cp;
00359         isc_uint64_t result;
00360 
00361         /*
00362          * Read an unsigned 48-bit integer in network byte order from 'b',
00363          * convert it to host byte order, and return it.
00364          */
00365 
00366         REQUIRE(ISC_BUFFER_VALID(b));
00367         REQUIRE(b->used - b->current >= 6);
00368 
00369         cp = isc_buffer_current(b);
00370         b->current += 6;
00371         result = ((isc_int64_t)(cp[0])) << 40;
00372         result |= ((isc_int64_t)(cp[1])) << 32;
00373         result |= ((isc_int64_t)(cp[2])) << 24;
00374         result |= ((isc_int64_t)(cp[3])) << 16;
00375         result |= ((isc_int64_t)(cp[4])) << 8;
00376         result |= ((isc_int64_t)(cp[5]));
00377 
00378         return (result);
00379 }
00380 
00381 void
00382 isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
00383         isc_uint16_t valhi;
00384         isc_uint32_t vallo;
00385 
00386         REQUIRE(ISC_BUFFER_VALID(b));
00387         REQUIRE(b->used + 6 <= b->length);
00388 
00389         valhi = (isc_uint16_t)(val >> 32);
00390         vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
00391         ISC__BUFFER_PUTUINT16(b, valhi);
00392         ISC__BUFFER_PUTUINT32(b, vallo);
00393 }
00394 
00395 void
00396 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
00397                    unsigned int length)
00398 {
00399         REQUIRE(ISC_BUFFER_VALID(b));
00400         REQUIRE(b->used + length <= b->length);
00401 
00402         ISC__BUFFER_PUTMEM(b, base, length);
00403 }
00404 
00405 void
00406 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
00407         unsigned int l;
00408         unsigned char *cp;
00409 
00410         REQUIRE(ISC_BUFFER_VALID(b));
00411         REQUIRE(source != NULL);
00412 
00413         /*
00414          * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
00415          */
00416         l = strlen(source);
00417 
00418         REQUIRE(l <= isc_buffer_availablelength(b));
00419 
00420         cp = isc_buffer_used(b);
00421         memmove(cp, source, l);
00422         b->used += l;
00423 }
00424 
00425 isc_result_t
00426 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
00427         unsigned char *base;
00428         unsigned int available;
00429 
00430         REQUIRE(ISC_BUFFER_VALID(b));
00431         REQUIRE(r != NULL);
00432 
00433         /*
00434          * XXXDCL
00435          */
00436         base = isc_buffer_used(b);
00437         available = isc_buffer_availablelength(b);
00438         if (r->length > available)
00439                 return (ISC_R_NOSPACE);
00440         memmove(base, r->base, r->length);
00441         b->used += r->length;
00442 
00443         return (ISC_R_SUCCESS);
00444 }
00445 
00446 isc_result_t
00447 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
00448                     unsigned int length)
00449 {
00450         isc_buffer_t *dbuf;
00451 
00452         REQUIRE(dynbuffer != NULL);
00453         REQUIRE(*dynbuffer == NULL);
00454 
00455         dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
00456         if (dbuf == NULL)
00457                 return (ISC_R_NOMEMORY);
00458 
00459         isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
00460                         length);
00461         dbuf->mctx = mctx;
00462 
00463         *dynbuffer = dbuf;
00464 
00465         return (ISC_R_SUCCESS);
00466 }
00467 
00468 isc_result_t
00469 isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length) {
00470         isc_buffer_t *dbuf;
00471 
00472         REQUIRE(dynbuffer != NULL);
00473         REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
00474         REQUIRE((*dynbuffer)->mctx != NULL);
00475 
00476         if ((*dynbuffer)->length > length)
00477                 return (ISC_R_NOSPACE);
00478 
00479         /*
00480          * XXXMUKS: This is far more expensive than plain realloc() as
00481          * it doesn't remap pages, but does ordinary copy. So is
00482          * isc_mem_reallocate(), which has additional issues.
00483          */
00484         dbuf = isc_mem_get((*dynbuffer)->mctx, length + sizeof(isc_buffer_t));
00485         if (dbuf == NULL)
00486                 return (ISC_R_NOMEMORY);
00487 
00488         memmove(dbuf, *dynbuffer, (*dynbuffer)->length + sizeof(isc_buffer_t));
00489         isc_mem_put(dbuf->mctx, *dynbuffer,
00490                     (*dynbuffer)->length + sizeof(isc_buffer_t));
00491 
00492         dbuf->base = ((unsigned char *)dbuf) + sizeof(isc_buffer_t);
00493         dbuf->length = length;
00494 
00495         INSIST(ISC_BUFFER_VALID(dbuf));
00496 
00497         *dynbuffer = dbuf;
00498 
00499         return (ISC_R_SUCCESS);
00500 }
00501 
00502 isc_result_t
00503 isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size) {
00504         isc_uint64_t len;
00505 
00506         REQUIRE(dynbuffer != NULL);
00507         REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
00508 
00509         len = (*dynbuffer)->length;
00510         if ((len - (*dynbuffer)->used) >= size)
00511                 return (ISC_R_SUCCESS);
00512 
00513         if ((*dynbuffer)->mctx == NULL)
00514                 return (ISC_R_NOSPACE);
00515 
00516         /* Round to nearest buffer size increment */
00517         len = size + (*dynbuffer)->used;
00518         len = (len + ISC_BUFFER_INCR - 1 - ((len - 1) % ISC_BUFFER_INCR));
00519 
00520         /* Cap at UINT_MAX */
00521         if (len > UINT_MAX) {
00522                 len = UINT_MAX;
00523         }
00524 
00525         if ((len - (*dynbuffer)->used) < size)
00526                 return (ISC_R_NOMEMORY);
00527 
00528         return (isc_buffer_reallocate(dynbuffer, (unsigned int) len));
00529 }
00530 
00531 void
00532 isc_buffer_free(isc_buffer_t **dynbuffer) {
00533         unsigned int real_length;
00534         isc_buffer_t *dbuf;
00535         isc_mem_t *mctx;
00536 
00537         REQUIRE(dynbuffer != NULL);
00538         REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
00539         REQUIRE((*dynbuffer)->mctx != NULL);
00540 
00541         dbuf = *dynbuffer;
00542         *dynbuffer = NULL;      /* destroy external reference */
00543 
00544         real_length = dbuf->length + sizeof(isc_buffer_t);
00545         mctx = dbuf->mctx;
00546         dbuf->mctx = NULL;
00547         isc_buffer_invalidate(dbuf);
00548 
00549         isc_mem_put(mctx, dbuf, real_length);
00550 }

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha