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