• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ngtcp2
3  *
4  * Copyright (c) 2017 ngtcp2 contributors
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include "ngtcp2_ringbuf.h"
26 
27 #include <assert.h>
28 #ifdef WIN32
29 #  include <intrin.h>
30 #endif
31 
32 #include "ngtcp2_macro.h"
33 
34 #if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64))
__popcnt(unsigned int x)35 unsigned int __popcnt(unsigned int x) {
36   unsigned int c = 0;
37   for (; x; ++c) {
38     x &= x - 1;
39   }
40   return c;
41 }
42 #endif
43 
ngtcp2_ringbuf_init(ngtcp2_ringbuf * rb,size_t nmemb,size_t size,const ngtcp2_mem * mem)44 int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
45                         const ngtcp2_mem *mem) {
46   uint8_t *buf = ngtcp2_mem_malloc(mem, nmemb * size);
47   if (buf == NULL) {
48     return NGTCP2_ERR_NOMEM;
49   }
50 
51   ngtcp2_ringbuf_buf_init(rb, nmemb, size, buf, mem);
52 
53   return 0;
54 }
55 
ngtcp2_ringbuf_buf_init(ngtcp2_ringbuf * rb,size_t nmemb,size_t size,uint8_t * buf,const ngtcp2_mem * mem)56 void ngtcp2_ringbuf_buf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
57                              uint8_t *buf, const ngtcp2_mem *mem) {
58 #ifdef WIN32
59   assert(1 == __popcnt((unsigned int)nmemb));
60 #else
61   assert(1 == __builtin_popcount((unsigned int)nmemb));
62 #endif
63 
64   rb->buf = buf;
65   rb->mem = mem;
66   rb->nmemb = nmemb;
67   rb->size = size;
68   rb->first = 0;
69   rb->len = 0;
70 }
71 
ngtcp2_ringbuf_free(ngtcp2_ringbuf * rb)72 void ngtcp2_ringbuf_free(ngtcp2_ringbuf *rb) {
73   if (rb == NULL) {
74     return;
75   }
76 
77   ngtcp2_mem_free(rb->mem, rb->buf);
78 }
79 
ngtcp2_ringbuf_push_front(ngtcp2_ringbuf * rb)80 void *ngtcp2_ringbuf_push_front(ngtcp2_ringbuf *rb) {
81   rb->first = (rb->first - 1) & (rb->nmemb - 1);
82   rb->len = ngtcp2_min(rb->nmemb, rb->len + 1);
83 
84   return (void *)&rb->buf[rb->first * rb->size];
85 }
86 
ngtcp2_ringbuf_push_back(ngtcp2_ringbuf * rb)87 void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb) {
88   size_t offset = (rb->first + rb->len) & (rb->nmemb - 1);
89 
90   if (rb->len == rb->nmemb) {
91     rb->first = (rb->first + 1) & (rb->nmemb - 1);
92   } else {
93     ++rb->len;
94   }
95 
96   return (void *)&rb->buf[offset * rb->size];
97 }
98 
ngtcp2_ringbuf_pop_front(ngtcp2_ringbuf * rb)99 void ngtcp2_ringbuf_pop_front(ngtcp2_ringbuf *rb) {
100   rb->first = (rb->first + 1) & (rb->nmemb - 1);
101   --rb->len;
102 }
103 
ngtcp2_ringbuf_pop_back(ngtcp2_ringbuf * rb)104 void ngtcp2_ringbuf_pop_back(ngtcp2_ringbuf *rb) {
105   assert(rb->len);
106   --rb->len;
107 }
108 
ngtcp2_ringbuf_resize(ngtcp2_ringbuf * rb,size_t len)109 void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len) {
110   assert(len <= rb->nmemb);
111   rb->len = len;
112 }
113 
ngtcp2_ringbuf_get(ngtcp2_ringbuf * rb,size_t offset)114 void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset) {
115   assert(offset < rb->len);
116   offset = (rb->first + offset) & (rb->nmemb - 1);
117   return &rb->buf[offset * rb->size];
118 }
119 
ngtcp2_ringbuf_full(ngtcp2_ringbuf * rb)120 int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->nmemb; }
121