89bbfd8225d43ca6c09233a723624cc64b7b2a82
[gem5.git] / base / circlebuf.cc
1 /*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <algorithm>
30 #include <string>
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "base/circlebuf.hh"
37 #include "base/cprintf.hh"
38 #include "base/intmath.hh"
39
40 using namespace std;
41
42 CircleBuf::CircleBuf(int l)
43 : _rollover(false), _buflen(l), _size(0), _start(0), _stop(0)
44 {
45 _buf = new char[_buflen];
46 }
47
48 CircleBuf::~CircleBuf()
49 {
50 if (_buf)
51 delete [] _buf;
52 }
53
54 void
55 CircleBuf::dump()
56 {
57 cprintf("start = %10d, stop = %10d, buflen = %10d\n",
58 _start, _stop, _buflen);
59 fflush(stdout);
60 ::write(STDOUT_FILENO, _buf, _buflen);
61 ::write(STDOUT_FILENO, "<\n", 2);
62 }
63
64 void
65 CircleBuf::flush()
66 {
67 _start = 0;
68 _stop = 0;
69 _rollover = false;
70 }
71
72 void
73 CircleBuf::read(char *b, int len)
74 {
75 _size -= len;
76 if (_size < 0)
77 _size = 0;
78
79 if (_stop > _start) {
80 len = min(len, _stop - _start);
81 memcpy(b, _buf + _start, len);
82 _start += len;
83 }
84 else {
85 int endlen = _buflen - _start;
86 if (endlen > len) {
87 memcpy(b, _buf + _start, len);
88 _start += len;
89 }
90 else {
91 memcpy(b, _buf + _start, endlen);
92 _start = min(len - endlen, _stop);
93 memcpy(b + endlen, _buf, _start);
94 }
95 }
96 }
97
98 void
99 CircleBuf::read(int fd, int len)
100 {
101 _size -= len;
102 if (_size < 0)
103 _size = 0;
104
105 if (_stop > _start) {
106 len = min(len, _stop - _start);
107 ::write(fd, _buf + _start, len);
108 _start += len;
109 }
110 else {
111 int endlen = _buflen - _start;
112 if (endlen > len) {
113 ::write(fd, _buf + _start, len);
114 _start += len;
115 }
116 else {
117 ::write(fd, _buf + _start, endlen);
118 _start = min(len - endlen, _stop);
119 ::write(fd, _buf, _start);
120 }
121 }
122 }
123
124 void
125 CircleBuf::read(int fd)
126 {
127 _size = 0;
128
129 if (_stop > _start) {
130 ::write(fd, _buf + _start, _stop - _start);
131 }
132 else {
133 ::write(fd, _buf + _start, _buflen - _start);
134 ::write(fd, _buf, _stop);
135 }
136
137 _start = _stop;
138 }
139
140 void
141 CircleBuf::read(ostream &out)
142 {
143 _size = 0;
144
145 if (_stop > _start) {
146 out.write(_buf + _start, _stop - _start);
147 }
148 else {
149 out.write(_buf + _start, _buflen - _start);
150 out.write(_buf, _stop);
151 }
152
153 _start = _stop;
154 }
155
156 void
157 CircleBuf::readall(int fd)
158 {
159 if (_rollover)
160 ::write(fd, _buf + _stop, _buflen - _stop);
161
162 ::write(fd, _buf, _stop);
163 _start = _stop;
164 }
165
166 void
167 CircleBuf::write(char b)
168 {
169 write(&b, 1);
170 }
171
172 void
173 CircleBuf::write(const char *b)
174 {
175 write(b, strlen(b));
176 }
177
178 void
179 CircleBuf::write(const char *b, int len)
180 {
181 if (len <= 0)
182 return;
183
184 _size += len;
185 if (_size > _buflen)
186 _size = _buflen;
187
188 int old_start = _start;
189 int old_stop = _stop;
190
191 if (len >= _buflen) {
192 _start = 0;
193 _stop = _buflen;
194 _rollover = true;
195 memcpy(_buf, b + (len - _buflen), _buflen);
196 return;
197 }
198
199 if (_stop + len <= _buflen) {
200 memcpy(_buf + _stop, b, len);
201 _stop += len;
202 } else {
203 int end_len = _buflen - old_stop;
204 _stop = len - end_len;
205 memcpy(_buf + old_stop, b, end_len);
206 memcpy(_buf, b + end_len, _stop);
207 _rollover = true;
208 }
209
210 if (old_start > old_stop && old_start < _stop ||
211 old_start < old_stop && _stop < old_stop)
212 _start = _stop + 1;
213 }