1 #ifndef BUFFER_H
2 #define BUFFER_H
3
4 #include <stdint.h>
5 #include <stdio.h>
6
7 /********************************************************
8 Audio Tools, a module and set of tools for manipulating audio data
9 Copyright (C) 2007-2014 Brian Langenberger
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *******************************************************/
25
26 /*bs_buffer can be thought of as a FIFO queue of byte data
27
28 buf_putc and other data writers append to "data"
29 starting from "window_end",
30 increasing the size of "data" and "data_size" as necessary to fit
31
32 buf_getc and other data readers pull from the beginning of "data"
33 starting from "window_start" to "window_end"
34
35 "rewindable" indicates whether "window_start" can go backwards
36 to point at previously read data
37 if false, data writers may slide the window down and reuse the buffer
38 if true, data writers may only append new data to the buffer*/
39 struct bs_buffer {
40 uint8_t* data;
41 unsigned data_size;
42 unsigned window_start;
43 unsigned window_end;
44 };
45
46 typedef unsigned buf_size_t;
47 typedef unsigned buf_pos_t;
48
49 /*returns a new bs_buffer struct which can be appended to and read from
50
51 it must be closed with buf_close() when no longer needed*/
52 struct bs_buffer*
53 buf_new(void);
54
55 /*deallocates buffer struct*/
56 void
57 buf_close(struct bs_buffer *stream);
58
59 /*returns the amount of data in the buffer in bytes*/
60 static inline unsigned
buf_window_size(const struct bs_buffer * stream)61 buf_window_size(const struct bs_buffer *stream)
62 {
63 return stream->window_end - stream->window_start;
64 }
65
66 /*returns the amount of data that can be added to the buffer
67 without resizing, in bytes*/
68 static inline unsigned
buf_unused_size(const struct bs_buffer * stream)69 buf_unused_size(const struct bs_buffer *stream)
70 {
71 return stream->data_size - stream->window_end;
72 }
73
74 /*returns the starting position of the buffer window
75 pointing to the first byte that may be read*/
76 static inline uint8_t*
buf_window_start(const struct bs_buffer * stream)77 buf_window_start(const struct bs_buffer *stream)
78 {
79 return stream->data + stream->window_start;
80 }
81
82 /*returns the ending position of the buffer window
83 pointing to the first byte that may be written*/
84 static inline uint8_t*
buf_window_end(const struct bs_buffer * stream)85 buf_window_end(const struct bs_buffer *stream)
86 {
87 return stream->data + stream->window_end;
88 }
89
90 /*resize buffer to fit at least "additional_bytes", if necessary
91
92 this may alter where window_start and window_end point to*/
93 void
94 buf_resize(struct bs_buffer *stream, unsigned additional_bytes);
95
96
97 /*clears out the buffer for possible reuse*/
98 static inline void
buf_reset(struct bs_buffer * stream)99 buf_reset(struct bs_buffer *stream)
100 {
101 stream->window_start = stream->window_end = 0;
102 }
103
104
105 /*** stdio-like functions for bs_buffer ***/
106
107 /*analagous to fgetc
108 returns byte at beginning of buffer
109 returns EOF if no bytes remain in buffer*/
110 static inline int
buf_getc(struct bs_buffer * stream)111 buf_getc(struct bs_buffer *stream)
112 {
113 if (stream->window_start < stream->window_end)
114 return stream->data[stream->window_start++];
115 else
116 return EOF;
117 }
118
119 /*analagous to fputc
120 places byte "i" at end of buffer*/
121 static inline int
buf_putc(int i,struct bs_buffer * stream)122 buf_putc(int i, struct bs_buffer *stream)
123 {
124 if (stream->window_end == stream->data_size) {
125 buf_resize(stream, 1);
126 }
127
128 stream->data[stream->window_end++] = (uint8_t)i;
129
130 return i;
131 }
132
133 /*analagous to fread
134
135 reads "data_size" bytes from "stream" to "data"
136 starting at the beginning of stream
137 returns the amount of bytes actually read
138 (which may be less than the amount requested)*/
139 unsigned
140 buf_read(struct bs_buffer *stream, uint8_t *data, unsigned data_size);
141
142 /*analagous to buf_read except that data is ignored rather than returned
143
144 returns the amount of bytes actually skipped*/
145 unsigned
146 buf_skip(struct bs_buffer *stream, unsigned data_size);
147
148 /*analgous to fwrite
149
150 appends "data_size" bytes from "data" to stream starting at "window_end"*/
151 void
152 buf_write(struct bs_buffer *stream, const uint8_t *data, unsigned data_size);
153
154 /*appends unconsumed data in "source" to "target"*/
155 static inline void
buf_extend(const struct bs_buffer * source,struct bs_buffer * target)156 buf_extend(const struct bs_buffer *source, struct bs_buffer* target)
157 {
158 buf_write(target, buf_window_start(source), buf_window_size(source));
159 }
160
161 #endif
162