Statistics
| Branch: | Tag: | Revision:

dvbd / circularbuffer.cpp @ bfdb7446

History | View | Annotate | Download (3.54 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "circularbuffer.h"
20
#include <cstring>
21
#include <iostream>
22

    
23
CircularBuffer::CircularBuffer(int initSize, int maxSize)
24
  : start(0), size(initSize), maxSize(maxSize), used(0), overflow(false)
25
{
26
  buffer = new char[size];
27
}
28

    
29
CircularBuffer::~CircularBuffer()
30
{
31
  delete [] buffer;
32
}
33

    
34

    
35
void CircularBuffer::grow()
36
{
37
  if (size == maxSize)
38
    return;
39

    
40
  int size1;
41
  int size2;
42

    
43
  if (start + used <= size) {
44
    size1 = used;
45
    size2 = 0;
46
  }
47
  else {
48
    size1 = size - start;
49
    size2 = used - size1;
50
  }
51

    
52
  int newSize = size * 2;
53
  if (newSize > maxSize)
54
    newSize = maxSize;
55
  
56
  char *newData = new char[newSize];
57
  memcpy(newData, buffer + start, size1);
58
  memcpy(newData + size1, buffer, size2);
59

    
60
  delete [] buffer;
61
  buffer = newData;
62
  size = newSize;
63
  start = 0;
64
}
65

    
66
bool CircularBuffer::write(const std::string &data)
67
{
68
  return write(data.data(), data.size());
69
}
70

    
71

    
72
bool CircularBuffer::write(const char *data, int count)
73
{
74
  while (size - used < count) {
75
    if (size == maxSize) {
76
      overflow = true;
77
      return false;
78
    }
79
    grow();
80
  }
81

    
82
  int tail = (start + used) % size;
83

    
84
  // We are using a circular buffer
85

    
86
  if (tail + count <= size) {
87
    memcpy(buffer + tail, data, count);
88
    used += count;
89
  }
90
  else {
91
    // Wrap around
92
    int size1 = size - tail;    //        - tail + size 
93
    int size2 = count - size1;        //  count + tail - size 
94

    
95
    memcpy(buffer + tail, data, size1);
96
    memcpy(buffer, data + size1, size2);
97
    used += count;
98
  }
99

    
100
  return true;
101
}
102

    
103
void CircularBuffer::discard(int count)
104
{
105
  if (count >= used)
106
    count = used;
107

    
108
  start = (start + count) % size;
109
  used -= count;
110
}
111

    
112
void CircularBuffer::getSections(char *&buffer1, int &count1, 
113
                               char *&buffer2, int &count2)
114
{
115
  buffer1 = buffer + start;
116
  buffer2 = buffer;
117

    
118
  if (start + used > size) {
119
    count1 = size - start;
120
    count2 = used - count1;
121
  }
122
  else {
123
    count1 = used;
124
    count2 = 0;
125
  }
126
}
127

    
128
bool CircularBuffer::read(char *data, int count)
129
{
130
  if (count > used)
131
    return false;
132

    
133
  char *buf1, *buf2;
134
  int len1, len2;
135

    
136
  getSections(buf1, len1, buf2, len2);
137

    
138
  if (count <= len1) 
139
    memcpy(data, buf1, count);
140
  else {
141
    memcpy(data, buf1, len1);
142
    memcpy(data + len1, buf2, count - len1);
143
  }
144

    
145
  start = (start + count) % size;
146
  used -= count;
147

    
148
  return true;
149
}
150

    
151
bool CircularBuffer::read(std::string &data, int count)
152
{
153
  char buf[count];
154
  bool result = read(buf, count);
155
  if (result) 
156
    data = std::string(buf, count);
157
  return result;
158
}
159

    
160
bool CircularBuffer::readLine(std::string &data, char ch)
161
{
162
  char *buf1, *buf2;
163
  int len1, len2;
164

    
165
  getSections(buf1, len1, buf2, len2);
166
  char *p = (char *) memchr(buf1, ch, len1);
167
  if (p != NULL) 
168
    return read(data, p - buf1 + 1);
169

    
170
  p = (char *) memchr(buf2, ch, len2);
171
  if (p == NULL)
172
    return false;
173

    
174
  int readLen = len1 + (p - buf2 + 1);
175
  return read(data, readLen);
176
}