LCOV - code coverage report
Current view: top level - core/support - slice_buffer.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 163 163 100.0 %
Date: 2015-12-10 22:15:08 Functions: 14 14 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/port_platform.h>
      35             : #include <grpc/support/slice_buffer.h>
      36             : 
      37             : #include <string.h>
      38             : 
      39             : #include <grpc/support/alloc.h>
      40             : #include <grpc/support/log.h>
      41             : #include <grpc/support/useful.h>
      42             : 
      43             : /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */
      44             : #define GROW(x) (3 * (x) / 2)
      45             : 
      46    67251399 : static void maybe_embiggen(gpr_slice_buffer *sb) {
      47    67251399 :   if (sb->count == sb->capacity) {
      48       25666 :     sb->capacity = GROW(sb->capacity);
      49       25666 :     GPR_ASSERT(sb->capacity > sb->count);
      50       25666 :     if (sb->slices == sb->inlined) {
      51        6495 :       sb->slices = gpr_malloc(sb->capacity * sizeof(gpr_slice));
      52        6495 :       memcpy(sb->slices, sb->inlined, sb->count * sizeof(gpr_slice));
      53             :     } else {
      54       19171 :       sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
      55             :     }
      56             :   }
      57    67251399 : }
      58             : 
      59    24143371 : void gpr_slice_buffer_init(gpr_slice_buffer *sb) {
      60    24143371 :   sb->count = 0;
      61    24143371 :   sb->length = 0;
      62    24143371 :   sb->capacity = GRPC_SLICE_BUFFER_INLINE_ELEMENTS;
      63    24143371 :   sb->slices = sb->inlined;
      64    24143371 : }
      65             : 
      66    20437293 : void gpr_slice_buffer_destroy(gpr_slice_buffer *sb) {
      67    20437293 :   gpr_slice_buffer_reset_and_unref(sb);
      68    20440421 :   if (sb->slices != sb->inlined) {
      69        6426 :     gpr_free(sb->slices);
      70             :   }
      71    20440421 : }
      72             : 
      73    42211813 : gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, size_t n) {
      74             :   gpr_slice *back;
      75             :   gpr_uint8 *out;
      76             : 
      77    42211813 :   sb->length += n;
      78             : 
      79    42211813 :   if (sb->count == 0) goto add_new;
      80    42211813 :   back = &sb->slices[sb->count - 1];
      81    42211813 :   if (back->refcount) goto add_new;
      82    36166249 :   if ((back->data.inlined.length + n) > sizeof(back->data.inlined.bytes))
      83     2154066 :     goto add_new;
      84    34012154 :   out = back->data.inlined.bytes + back->data.inlined.length;
      85    34012154 :   back->data.inlined.length = (gpr_uint8)(back->data.inlined.length + n);
      86    34012154 :   return out;
      87             : 
      88             : add_new:
      89     8199659 :   maybe_embiggen(sb);
      90     8200101 :   back = &sb->slices[sb->count];
      91     8200101 :   sb->count++;
      92     8200101 :   back->refcount = NULL;
      93     8200101 :   back->data.inlined.length = (gpr_uint8)n;
      94     8200101 :   return back->data.inlined.bytes;
      95             : }
      96             : 
      97    54853247 : size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, gpr_slice s) {
      98    54853247 :   size_t out = sb->count;
      99    54853247 :   maybe_embiggen(sb);
     100    54876271 :   sb->slices[out] = s;
     101    54876271 :   sb->length += GPR_SLICE_LENGTH(s);
     102    54876271 :   sb->count = out + 1;
     103    54876271 :   return out;
     104             : }
     105             : 
     106    39654691 : void gpr_slice_buffer_add(gpr_slice_buffer *sb, gpr_slice s) {
     107    39654691 :   size_t n = sb->count;
     108             :   /* if both the last slice in the slice buffer and the slice being added
     109             :      are inlined (that is, that they carry their data inside the slice data
     110             :      structure), and the back slice is not full, then concatenate directly
     111             :      into the back slice, preventing many small slices being passed into
     112             :      writes */
     113    39654691 :   if (!s.refcount && n) {
     114    18381557 :     gpr_slice *back = &sb->slices[n - 1];
     115    18381557 :     if (!back->refcount && back->data.inlined.length < GPR_SLICE_INLINED_SIZE) {
     116    18037018 :       if (s.data.inlined.length + back->data.inlined.length <=
     117             :           GPR_SLICE_INLINED_SIZE) {
     118    13791451 :         memcpy(back->data.inlined.bytes + back->data.inlined.length,
     119    13791183 :                s.data.inlined.bytes, s.data.inlined.length);
     120    13791451 :         back->data.inlined.length =
     121    13791451 :             (gpr_uint8)(back->data.inlined.length + s.data.inlined.length);
     122             :       } else {
     123     4245567 :         size_t cp1 = GPR_SLICE_INLINED_SIZE - back->data.inlined.length;
     124     4245567 :         memcpy(back->data.inlined.bytes + back->data.inlined.length,
     125             :                s.data.inlined.bytes, cp1);
     126     4245567 :         back->data.inlined.length = GPR_SLICE_INLINED_SIZE;
     127     4245567 :         maybe_embiggen(sb);
     128     4244797 :         back = &sb->slices[n];
     129     4244797 :         sb->count = n + 1;
     130     4244797 :         back->refcount = NULL;
     131     4244797 :         back->data.inlined.length = (gpr_uint8)(s.data.inlined.length - cp1);
     132     4244797 :         memcpy(back->data.inlined.bytes, s.data.inlined.bytes + cp1,
     133     4244652 :                s.data.inlined.length - cp1);
     134             :       }
     135    18036248 :       sb->length += s.data.inlined.length;
     136    57755738 :       return; /* early out */
     137             :     }
     138             :   }
     139    21617673 :   gpr_slice_buffer_add_indexed(sb, s);
     140             : }
     141             : 
     142     4361009 : void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *s, size_t n) {
     143             :   size_t i;
     144     8996607 :   for (i = 0; i < n; i++) {
     145     4633082 :     gpr_slice_buffer_add(sb, s[i]);
     146             :   }
     147     4363525 : }
     148             : 
     149          26 : void gpr_slice_buffer_pop(gpr_slice_buffer *sb) {
     150          26 :   if (sb->count != 0) {
     151          20 :     size_t count = --sb->count;
     152          20 :     sb->length -= GPR_SLICE_LENGTH(sb->slices[count]);
     153             :   }
     154          26 : }
     155             : 
     156    41131557 : void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) {
     157             :   size_t i;
     158             : 
     159    99017351 :   for (i = 0; i < sb->count; i++) {
     160    57867882 :     gpr_slice_unref(sb->slices[i]);
     161             :   }
     162             : 
     163    41149469 :   sb->count = 0;
     164    41149469 :   sb->length = 0;
     165    41149469 : }
     166             : 
     167    42469065 : void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) {
     168    42469065 :   GPR_SWAP(size_t, a->count, b->count);
     169    42469065 :   GPR_SWAP(size_t, a->capacity, b->capacity);
     170    42469065 :   GPR_SWAP(size_t, a->length, b->length);
     171             : 
     172    42469065 :   if (a->slices == a->inlined) {
     173    19411748 :     if (b->slices == b->inlined) {
     174             :       /* swap contents of inlined buffer */
     175             :       gpr_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
     176     8719446 :       memcpy(temp, a->slices, b->count * sizeof(gpr_slice));
     177     8719446 :       memcpy(a->slices, b->slices, a->count * sizeof(gpr_slice));
     178     8719446 :       memcpy(b->slices, temp, b->count * sizeof(gpr_slice));
     179             :     } else {
     180             :       /* a is inlined, b is not - copy a inlined into b, fix pointers */
     181    10692302 :       a->slices = b->slices;
     182    10692302 :       b->slices = b->inlined;
     183    10692302 :       memcpy(b->slices, a->inlined, b->count * sizeof(gpr_slice));
     184             :     }
     185    23057317 :   } else if (b->slices == b->inlined) {
     186             :     /* b is inlined, a is not - copy b inlined int a, fix pointers */
     187    10685116 :     b->slices = a->slices;
     188    10685116 :     a->slices = a->inlined;
     189    10685116 :     memcpy(a->slices, b->inlined, a->count * sizeof(gpr_slice));
     190             :   } else {
     191             :     /* no inlining: easy swap */
     192    12372201 :     GPR_SWAP(gpr_slice *, a->slices, b->slices);
     193             :   }
     194    42469065 : }
     195             : 
     196    11002858 : void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) {
     197             :   /* anything to move? */
     198    11002858 :   if (src->count == 0) {
     199     7033190 :     return;
     200             :   }
     201             :   /* anything in dst? */
     202     3968998 :   if (dst->count == 0) {
     203        5556 :     gpr_slice_buffer_swap(src, dst);
     204        5557 :     return;
     205             :   }
     206             :   /* both buffers have data - copy, and reset src */
     207     3963442 :   gpr_slice_buffer_addn(dst, src->slices, src->count);
     208     3962996 :   src->count = 0;
     209     3962996 :   src->length = 0;
     210             : }
     211             : 
     212     4489531 : void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n,
     213             :                                  gpr_slice_buffer *dst) {
     214             :   size_t src_idx;
     215     4489531 :   size_t output_len = dst->length + n;
     216     4489531 :   size_t new_input_len = src->length - n;
     217     4489531 :   GPR_ASSERT(src->length >= n);
     218     4489531 :   if (src->length == n) {
     219     4485706 :     gpr_slice_buffer_move_into(src, dst);
     220     4485339 :     return;
     221             :   }
     222        3717 :   src_idx = 0;
     223        8896 :   while (src_idx < src->capacity) {
     224        5179 :     gpr_slice slice = src->slices[src_idx];
     225        5179 :     size_t slice_len = GPR_SLICE_LENGTH(slice);
     226        5179 :     if (n > slice_len) {
     227        1354 :       gpr_slice_buffer_add(dst, slice);
     228        1354 :       n -= slice_len;
     229        1354 :       src_idx++;
     230        3825 :     } else if (n == slice_len) {
     231           1 :       gpr_slice_buffer_add(dst, slice);
     232           1 :       src_idx++;
     233        3826 :       break;
     234             :     } else { /* n < slice_len */
     235        3824 :       src->slices[src_idx] = gpr_slice_split_tail(&slice, n);
     236        3824 :       GPR_ASSERT(GPR_SLICE_LENGTH(slice) == n);
     237        3824 :       GPR_ASSERT(GPR_SLICE_LENGTH(src->slices[src_idx]) == slice_len - n);
     238        3824 :       gpr_slice_buffer_add(dst, slice);
     239        3824 :       break;
     240             :     }
     241             :   }
     242        3825 :   GPR_ASSERT(dst->length == output_len);
     243        3825 :   memmove(src->slices, src->slices + src_idx,
     244        3825 :           sizeof(gpr_slice) * (src->count - src_idx));
     245        3825 :   src->count -= src_idx;
     246        3825 :   src->length = new_input_len;
     247        3825 :   GPR_ASSERT(src->count > 0);
     248             : }
     249             : 
     250     2456567 : void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n,
     251             :                                gpr_slice_buffer *garbage) {
     252     2456567 :   GPR_ASSERT(n <= sb->length);
     253     2456567 :   sb->length -= n;
     254             :   for (;;) {
     255     4554623 :     size_t idx = sb->count - 1;
     256     4554623 :     gpr_slice slice = sb->slices[idx];
     257     4554623 :     size_t slice_len = GPR_SLICE_LENGTH(slice);
     258     4554623 :     if (slice_len > n) {
     259     2294889 :       sb->slices[idx] = gpr_slice_split_head(&slice, slice_len - n);
     260     2294904 :       gpr_slice_buffer_add_indexed(garbage, slice);
     261     2294904 :       return;
     262     2259734 :     } else if (slice_len == n) {
     263      161672 :       gpr_slice_buffer_add_indexed(garbage, slice);
     264      161672 :       sb->count = idx;
     265      161672 :       return;
     266             :     } else {
     267     2098062 :       gpr_slice_buffer_add_indexed(garbage, slice);
     268     2098056 :       n -= slice_len;
     269     2098056 :       sb->count = idx;
     270             :     }
     271     2098056 :   }
     272             : }
     273             : 
     274     3192058 : gpr_slice gpr_slice_buffer_take_first(gpr_slice_buffer *sb) {
     275             :   gpr_slice slice;
     276     3192058 :   GPR_ASSERT(sb->count > 0);
     277     3192058 :   slice = sb->slices[0];
     278     3192058 :   memmove(&sb->slices[0], &sb->slices[1], (sb->count - 1) * sizeof(gpr_slice));
     279     3192058 :   sb->count--;
     280     3192058 :   sb->length -= GPR_SLICE_LENGTH(slice);
     281     3192058 :   return slice;
     282             : }

Generated by: LCOV version 1.11