LCOV - code coverage report
Current view: top level - src/core/support - slice_buffer.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 123 126 97.6 %
Date: 2015-10-10 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2015, Google Inc.
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are
       8             :  * met:
       9             :  *
      10             :  *     * Redistributions of source code must retain the above copyright
      11             :  * notice, this list of conditions and the following disclaimer.
      12             :  *     * Redistributions in binary form must reproduce the above
      13             :  * copyright notice, this list of conditions and the following disclaimer
      14             :  * in the documentation and/or other materials provided with the
      15             :  * distribution.
      16             :  *     * Neither the name of Google Inc. nor the names of its
      17             :  * contributors may be used to endorse or promote products derived from
      18             :  * this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : #include <grpc/support/slice_buffer.h>
      35             : 
      36             : #include <string.h>
      37             : 
      38             : #include <grpc/support/alloc.h>
      39             : #include <grpc/support/log.h>
      40             : #include <grpc/support/useful.h>
      41             : 
      42             : /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */
      43             : #define GROW(x) (3 * (x) / 2)
      44             : 
      45    41606559 : static void maybe_embiggen(gpr_slice_buffer *sb) {
      46    41606559 :   if (sb->count == sb->capacity) {
      47        9816 :     sb->capacity = GROW(sb->capacity);
      48        9816 :     GPR_ASSERT(sb->capacity > sb->count);
      49        9816 :     if (sb->slices == sb->inlined) {
      50        3637 :       sb->slices = gpr_malloc(sb->capacity * sizeof(gpr_slice));
      51        3637 :       memcpy(sb->slices, sb->inlined, sb->count * sizeof(gpr_slice));
      52             :     } else {
      53        6179 :       sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
      54             :     }
      55             :   }
      56    41606559 : }
      57             : 
      58    16750614 : void gpr_slice_buffer_init(gpr_slice_buffer *sb) {
      59    16750614 :   sb->count = 0;
      60    16750614 :   sb->length = 0;
      61    16750614 :   sb->capacity = GRPC_SLICE_BUFFER_INLINE_ELEMENTS;
      62    16750614 :   sb->slices = sb->inlined;
      63    16750614 : }
      64             : 
      65    11324255 : void gpr_slice_buffer_destroy(gpr_slice_buffer *sb) {
      66    11324255 :   gpr_slice_buffer_reset_and_unref(sb);
      67    11325901 :   if (sb->slices != sb->inlined) {
      68        3637 :     gpr_free(sb->slices);
      69             :   }
      70    11325901 : }
      71             : 
      72    19475097 : gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, size_t n) {
      73             :   gpr_slice *back;
      74             :   gpr_uint8 *out;
      75             : 
      76    19475097 :   sb->length += n;
      77             : 
      78    19475097 :   if (sb->count == 0) goto add_new;
      79    19475097 :   back = &sb->slices[sb->count - 1];
      80    19475097 :   if (back->refcount) goto add_new;
      81    19429103 :   if ((back->data.inlined.length + n) > sizeof(back->data.inlined.bytes))
      82     1406798 :     goto add_new;
      83    18022305 :   out = back->data.inlined.bytes + back->data.inlined.length;
      84    18022305 :   back->data.inlined.length = (gpr_uint8)(back->data.inlined.length + n);
      85    18022305 :   return out;
      86             : 
      87             : add_new:
      88     1452792 :   maybe_embiggen(sb);
      89     1452694 :   back = &sb->slices[sb->count];
      90     1452694 :   sb->count++;
      91     1452694 :   back->refcount = NULL;
      92     1452694 :   back->data.inlined.length = (gpr_uint8)n;
      93     1452694 :   return back->data.inlined.bytes;
      94             : }
      95             : 
      96    37013659 : size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, gpr_slice s) {
      97    37013659 :   size_t out = sb->count;
      98    37013659 :   maybe_embiggen(sb);
      99    37082197 :   sb->slices[out] = s;
     100    37082197 :   sb->length += GPR_SLICE_LENGTH(s);
     101    37082197 :   sb->count = out + 1;
     102    37082197 :   return out;
     103             : }
     104             : 
     105    24288703 : void gpr_slice_buffer_add(gpr_slice_buffer *sb, gpr_slice s) {
     106    24288703 :   size_t n = sb->count;
     107             :   /* if both the last slice in the slice buffer and the slice being added
     108             :      are inlined (that is, that they carry their data inside the slice data
     109             :      structure), and the back slice is not full, then concatenate directly
     110             :      into the back slice, preventing many small slices being passed into
     111             :      writes */
     112    24288703 :   if (!s.refcount && n) {
     113    13405211 :     gpr_slice *back = &sb->slices[n - 1];
     114    13405211 :     if (!back->refcount && back->data.inlined.length < GPR_SLICE_INLINED_SIZE) {
     115    12467704 :       if (s.data.inlined.length + back->data.inlined.length <=
     116             :           GPR_SLICE_INLINED_SIZE) {
     117     9327927 :         memcpy(back->data.inlined.bytes + back->data.inlined.length,
     118     9327927 :                s.data.inlined.bytes, s.data.inlined.length);
     119     9327927 :         back->data.inlined.length =
     120     9327927 :             (gpr_uint8)(back->data.inlined.length + s.data.inlined.length);
     121             :       } else {
     122     3139777 :         size_t cp1 = GPR_SLICE_INLINED_SIZE - back->data.inlined.length;
     123     3139777 :         memcpy(back->data.inlined.bytes + back->data.inlined.length,
     124             :                s.data.inlined.bytes, cp1);
     125     3139777 :         back->data.inlined.length = GPR_SLICE_INLINED_SIZE;
     126     3139777 :         maybe_embiggen(sb);
     127     3139759 :         back = &sb->slices[n];
     128     3139759 :         sb->count = n + 1;
     129     3139759 :         back->refcount = NULL;
     130     3139759 :         back->data.inlined.length = (gpr_uint8)(s.data.inlined.length - cp1);
     131     3139759 :         memcpy(back->data.inlined.bytes, s.data.inlined.bytes + cp1,
     132     3139759 :                s.data.inlined.length - cp1);
     133             :       }
     134    12467686 :       sb->length += s.data.inlined.length;
     135    36820842 :       return; /* early out */
     136             :     }
     137             :   }
     138    11820999 :   gpr_slice_buffer_add_indexed(sb, s);
     139             : }
     140             : 
     141      398367 : void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *s, size_t n) {
     142             :   size_t i;
     143     1028826 :   for (i = 0; i < n; i++) {
     144      630459 :     gpr_slice_buffer_add(sb, s[i]);
     145             :   }
     146      398367 : }
     147             : 
     148          26 : void gpr_slice_buffer_pop(gpr_slice_buffer *sb) {
     149          26 :   if (sb->count != 0) {
     150          20 :     size_t count = --sb->count;
     151          20 :     sb->length -= GPR_SLICE_LENGTH(sb->slices[count]);
     152             :   }
     153          26 : }
     154             : 
     155    27734999 : void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) {
     156             :   size_t i;
     157             : 
     158    62769865 :   for (i = 0; i < sb->count; i++) {
     159    34993531 :     gpr_slice_unref(sb->slices[i]);
     160             :   }
     161             : 
     162    27776334 :   sb->count = 0;
     163    27776334 :   sb->length = 0;
     164    27776334 : }
     165             : 
     166    15994073 : void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) {
     167    15994073 :   GPR_SWAP(size_t, a->count, b->count);
     168    15994073 :   GPR_SWAP(size_t, a->capacity, b->capacity);
     169    15994073 :   GPR_SWAP(size_t, a->length, b->length);
     170             : 
     171    15994073 :   if (a->slices == a->inlined) {
     172     9621173 :     if (b->slices == b->inlined) {
     173             :       /* swap contents of inlined buffer */
     174             :       gpr_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
     175     6150159 :       memcpy(temp, a->slices, b->count * sizeof(gpr_slice));
     176     6150159 :       memcpy(a->slices, b->slices, a->count * sizeof(gpr_slice));
     177     6150159 :       memcpy(b->slices, temp, b->count * sizeof(gpr_slice));
     178             :     } else {
     179             :       /* a is inlined, b is not - copy a inlined into b, fix pointers */
     180     3471014 :       a->slices = b->slices;
     181     3471014 :       b->slices = b->inlined;
     182     3471014 :       memcpy(b->slices, a->inlined, b->count * sizeof(gpr_slice));
     183             :     }
     184     6372900 :   } else if (b->slices == b->inlined) {
     185             :     /* b is inlined, a is not - copy b inlined int a, fix pointers */
     186     3468672 :     b->slices = a->slices;
     187     3468672 :     a->slices = a->inlined;
     188     3468672 :     memcpy(a->slices, b->inlined, a->count * sizeof(gpr_slice));
     189             :   } else {
     190             :     /* no inlining: easy swap */
     191     2904228 :     GPR_SWAP(gpr_slice *, a->slices, b->slices);
     192             :   }
     193    15994073 : }
     194             : 
     195     2466029 : void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) {
     196             :   /* anything to move? */
     197     2466029 :   if (src->count == 0) {
     198     2462349 :     return;
     199             :   }
     200             :   /* anything in dst? */
     201        3680 :   if (dst->count == 0) {
     202        3680 :     gpr_slice_buffer_swap(src, dst);
     203        3680 :     return;
     204             :   }
     205             :   /* both buffers have data - copy, and reset src */
     206           0 :   gpr_slice_buffer_addn(dst, src->slices, src->count);
     207           0 :   src->count = 0;
     208           0 :   src->length = 0;
     209             : }
     210             : 
     211     1415918 : void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n,
     212             :                                gpr_slice_buffer *garbage) {
     213     1415918 :   GPR_ASSERT(n <= sb->length);
     214     1415918 :   sb->length -= n;
     215             :   for (;;) {
     216     2685740 :     size_t idx = sb->count - 1;
     217     2685740 :     gpr_slice slice = sb->slices[idx];
     218     2685740 :     size_t slice_len = GPR_SLICE_LENGTH(slice);
     219     2685740 :     if (slice_len > n) {
     220     1402536 :       sb->slices[idx] = gpr_slice_split_head(&slice, slice_len - n);
     221     1402572 :       gpr_slice_buffer_add_indexed(garbage, slice);
     222     1402570 :       return;
     223     1283204 :     } else if (slice_len == n) {
     224       13355 :       gpr_slice_buffer_add_indexed(garbage, slice);
     225       13355 :       sb->count = idx;
     226       13355 :       return;
     227             :     } else {
     228     1269849 :       gpr_slice_buffer_add_indexed(garbage, slice);
     229     1269822 :       n -= slice_len;
     230     1269822 :       sb->count = idx;
     231             :     }
     232     1269822 :   }
     233             : }

Generated by: LCOV version 1.10