Neovim Home
src
nvim
rbuffer.h
Go to the documentation of this file.
1
// Specialized ring buffer. This is basically an array that wraps read/write
2
// pointers around the memory region. It should be more efficient than the old
3
// RBuffer which required memmove() calls to relocate read/write positions.
4
//
5
// The main purpose of RBuffer is simplify memory management when reading from
6
// uv_stream_t instances:
7
//
8
// - The event loop writes data to a RBuffer, advancing the write pointer
9
// - The main loop reads data, advancing the read pointer
10
// - If the buffer becomes full(size == capacity) the rstream is temporarily
11
// stopped(automatic backpressure handling)
12
//
13
// Reference: http://en.wikipedia.org/wiki/Circular_buffer
14
#ifndef NVIM_RBUFFER_H
15
#define NVIM_RBUFFER_H
16
17
#include <stddef.h>
18
#include <stdint.h>
19
20
// Macros that simplify working with the read/write pointers directly by hiding
21
// ring buffer wrap logic. Some examples:
22
//
23
// - Pass the write pointer to a function(write_data) that incrementally
24
// produces data, returning the number of bytes actually written to the
25
// ring buffer:
26
//
27
// RBUFFER_UNTIL_FULL(rbuf, ptr, cnt)
28
// rbuffer_produced(rbuf, write_data(state, ptr, cnt));
29
//
30
// - Pass the read pointer to a function(read_data) that incrementally
31
// consumes data, returning the number of bytes actually read from the
32
// ring buffer:
33
//
34
// RBUFFER_UNTIL_EMPTY(rbuf, ptr, cnt)
35
// rbuffer_consumed(rbuf, read_data(state, ptr, cnt));
36
//
37
// Note that the rbuffer_{produced,consumed} calls are necessary or these macros
38
// create infinite loops
39
//
40
// -V:RBUFFER_UNTIL_EMPTY:1044
41
#define RBUFFER_UNTIL_EMPTY(buf, rptr, rcnt) \
42
for (size_t rcnt = 0, _r = 1; _r; _r = 0)
/* NOLINT(readability/braces) */
\
43
for (char *rptr = rbuffer_read_ptr(buf, &rcnt);
/* NOLINT(readability/braces) */
\
44
buf->size; \
45
rptr = rbuffer_read_ptr(buf, &rcnt))
46
47
#define RBUFFER_UNTIL_FULL(buf, wptr, wcnt) \
48
for (size_t wcnt = 0, _r = 1; _r; _r = 0)
/* NOLINT(readability/braces) */
\
49
for (char *wptr = rbuffer_write_ptr(buf, &wcnt);
/* NOLINT(readability/braces) */
\
50
rbuffer_space(buf); \
51
wptr = rbuffer_write_ptr(buf, &wcnt))
52
53
54
// Iteration
55
#define RBUFFER_EACH(buf, c, i) \
56
for (size_t i = 0;
/* NOLINT(readability/braces) */
\
57
i < buf->size; \
58
i = buf->size) \
59
for (char c = 0;
/* NOLINT(readability/braces) */
\
60
i < buf->size ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
61
i++)
62
63
#define RBUFFER_EACH_REVERSE(buf, c, i) \
64
for (size_t i = buf->size;
/* NOLINT(readability/braces) */
\
65
i != SIZE_MAX; \
66
i = SIZE_MAX) \
67
for (char c = 0;
/* NOLINT(readability/braces) */
\
68
i-- > 0 ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
69
)
70
71
typedef
struct
rbuffer
RBuffer
;
75
typedef
void
(*
rbuffer_callback
)(
RBuffer
*
buf
,
void
*
data
);
76
77
struct
rbuffer
{
78
rbuffer_callback
full_cb
,
nonfull_cb
;
79
void
*
data
;
80
size_t
size
;
81
// helper memory used to by rbuffer_reset if required
82
char
*
temp
;
83
char
*
end_ptr
, *
read_ptr
, *
write_ptr
;
84
char
start_ptr
[];
85
};
86
87
#ifdef INCLUDE_GENERATED_DECLARATIONS
88
# include "rbuffer.h.generated.h"
89
#endif
90
91
#endif // NVIM_RBUFFER_H
rbuffer::end_ptr
char * end_ptr
Definition:
rbuffer.h:83
rbuffer::full_cb
rbuffer_callback full_cb
Definition:
rbuffer.h:78
rbuffer::data
void * data
Definition:
rbuffer.h:79
rbuffer::start_ptr
char start_ptr[]
Definition:
rbuffer.h:84
rbuffer_callback
void(* rbuffer_callback)(RBuffer *buf, void *data)
Definition:
rbuffer.h:75
rbuffer::write_ptr
char * write_ptr
Definition:
rbuffer.h:83
rbuffer::nonfull_cb
rbuffer_callback nonfull_cb
Definition:
rbuffer.h:78
void
void(WINAPI *pClosePseudoConsole)(HPCON)
rbuffer
Definition:
rbuffer.h:77
rbuffer::size
size_t size
Definition:
rbuffer.h:80
rbuffer::read_ptr
char * read_ptr
Definition:
rbuffer.h:83
buf
char *const buf
Definition:
encode.c:234
rbuffer::temp
char * temp
Definition:
rbuffer.h:82