1 /*
2  * MOC - music on console
3  * Copyright (C) 2005 Damian Pietras <daper@daper.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  */
11 
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15 
16 #include <assert.h>
17 #include <string.h>
18 
19 #include "common.h"
20 #include "fifo_buf.h"
21 
22 /* Initialize the fifo_buf structure with empty buffer of the given size. */
fifo_buf_init(struct fifo_buf * b,const size_t size)23 void fifo_buf_init (struct fifo_buf *b, const size_t size)
24 {
25 	assert (b != NULL);
26 	assert (size > 0);
27 
28 	b->buf = (char *)xmalloc (size);
29 	b->size = size;
30 	b->pos = 0;
31 	b->fill = 0;
32 }
33 
34 /* Destroy the buffer object. */
fifo_buf_destroy(struct fifo_buf * b)35 void fifo_buf_destroy (struct fifo_buf *b)
36 {
37 	assert (b != NULL);
38 
39 	free (b->buf);
40 	b->buf = NULL;
41 }
42 
43 /* Put data into the buffer. Returns number of bytes actually put. */
fifo_buf_put(struct fifo_buf * b,const char * data,size_t size)44 size_t fifo_buf_put (struct fifo_buf *b, const char *data, size_t size)
45 {
46 	size_t written = 0;
47 
48 	assert (b != NULL);
49 	assert (b->buf != NULL);
50 
51 	while (b->fill < b->size && written < size) {
52 		size_t write_from;
53 		size_t to_write;
54 
55 		if (b->pos + b->fill < b->size) {
56 			write_from = b->pos + b->fill;
57 			to_write = b->size - (b->pos + b->fill);
58 		}
59 		else {
60 			write_from = b->fill - b->size + b->pos;
61 			to_write = b->size - b->fill;
62 		}
63 
64 		if (to_write > size - written)
65 			to_write = size - written;
66 
67 		memcpy (b->buf + write_from, data + written, to_write);
68 		b->fill += to_write;
69 		written += to_write;
70 	}
71 
72 	return written;
73 }
74 
75 /* Copy data from the beginning of the buffer to the user buffer. Returns the
76  * number of bytes copied. */
fifo_buf_peek(struct fifo_buf * b,char * user_buf,size_t user_buf_size)77 size_t fifo_buf_peek (struct fifo_buf *b, char *user_buf,
78 		size_t user_buf_size)
79 {
80 	size_t user_buf_pos = 0, written = 0;
81 	ssize_t left, pos;
82 
83 	assert (b != NULL);
84 	assert (b->buf != NULL);
85 
86 	left = b->fill;
87 	pos = b->pos;
88 
89 	while (left && written < user_buf_size) {
90 		size_t to_copy = pos + left <= b->size
91 			? left : b->size - pos;
92 
93 		if (to_copy > user_buf_size - written)
94 			to_copy = user_buf_size - written;
95 
96 		memcpy (user_buf + user_buf_pos, b->buf + pos, to_copy);
97 		user_buf_pos += to_copy;
98 		written += to_copy;
99 
100 		left -= to_copy;
101 		pos += to_copy;
102 		if (pos == b->size)
103 			pos = 0;
104 	}
105 
106 	return written;
107 }
108 
fifo_buf_get(struct fifo_buf * b,char * user_buf,size_t user_buf_size)109 size_t fifo_buf_get (struct fifo_buf *b, char *user_buf,
110 		size_t user_buf_size)
111 {
112 	size_t user_buf_pos = 0, written = 0;
113 
114 	assert (b != NULL);
115 	assert (b->buf != NULL);
116 
117 	while (b->fill && written < user_buf_size) {
118 		size_t to_copy = b->pos + b->fill <= b->size
119 			? b->fill : b->size - b->pos;
120 
121 		if (to_copy > user_buf_size - written)
122 			to_copy = user_buf_size - written;
123 
124 		memcpy (user_buf + user_buf_pos, b->buf + b->pos, to_copy);
125 		user_buf_pos += to_copy;
126 		written += to_copy;
127 
128 		b->fill -= to_copy;
129 		b->pos += to_copy;
130 		if (b->pos == b->size)
131 			b->pos = 0;
132 	}
133 
134 	return written;
135 }
136 
137 /* Get the amount of free space in the buffer. */
fifo_buf_get_space(const struct fifo_buf * b)138 size_t fifo_buf_get_space (const struct fifo_buf *b)
139 {
140 	assert (b != NULL);
141 	assert (b->buf != NULL);
142 
143 	return b->size - b->fill;
144 
145 }
146 
fifo_buf_get_fill(const struct fifo_buf * b)147 size_t fifo_buf_get_fill (const struct fifo_buf *b)
148 {
149 	assert (b != NULL);
150 	return b->fill;
151 }
152 
fifo_buf_get_size(const struct fifo_buf * b)153 size_t fifo_buf_get_size (const struct fifo_buf *b)
154 {
155 	assert (b != NULL);
156 	return b->size;
157 }
158 
fifo_buf_clear(struct fifo_buf * b)159 void fifo_buf_clear (struct fifo_buf *b)
160 {
161 	assert (b != NULL);
162 	b->fill = 0;
163 }
164