id3lib 3.8.3
io_decorators.cpp
Go to the documentation of this file.
1// $Id: io_decorators.cpp,v 1.4 2002/07/02 22:13:40 t1mpy Exp $
2
3// id3lib: a C++ library for creating and manipulating id3v1/v2 tags
4// Copyright 1999, 2000 Scott Thomas Haug
5
6// This library is free software; you can redistribute it and/or modify it
7// under the terms of the GNU Library General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// This library is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14// License for more details.
15//
16// You should have received a copy of the GNU Library General Public License
17// along with this library; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20// The id3lib authors encourage improvements and optimisations to be sent to
21// the id3lib coordinator. Please see the README file for details on where to
22// send such submissions. See the AUTHORS file for a list of people who have
23// contributed to id3lib. See the ChangeLog file for a list of changes to
24// id3lib. These files are distributed with id3lib at
25// http://download.sourceforge.net/id3lib/
26
27#if defined HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31
32
33#include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"
34#include "zlib.h"
35
36using namespace dami;
37
38void io::WindowedReader::setWindow(pos_type beg, size_type size)
39{
40 ID3D_NOTICE( "WindowedReader::setWindow() [beg, size] = [" <<
41 this->getBeg() << ", " << size << "]" );
42 pos_type cur = this->getCur();
43
44 // reset the end marker so as to avoid errors
45 this->setEnd(_reader.getEnd());
46
47 // set the beginning marker
48 this->setBeg(beg);
49
50 // since the characters might be more than a byte in size, we need to
51 // manually get all the chars to set the window appropriately
52 this->setCur(beg);
53 ID3D_NOTICE( "WindowedReader::setWindow(): after setCur(beg), cur = "<<
54 this->getCur() );
55
56 this->skipChars(size);
57 ID3D_NOTICE( "WindowedReader::setWindow(): after skipChars, cur = " <<
58 this->getCur() );
59
60 this->setEnd(this->getCur());
61
62 ID3D_NOTICE( "WindowedReader::setWindow() [beg, cur, end] = [" << this->getBeg() << ", " << this->getCur() << ", " << this->getEnd() << "]" );
63
64
65 // reset the stream
66 this->setCur(cur);
67}
68
69ID3_Reader::pos_type io::WindowedReader::setBeg(pos_type beg)
70{
71 // make sure the position we want to set to isn't past the current
72 // end position or the superclass's beginning position
73 if (beg <= this->getEnd() && beg >= _reader.getBeg())
74 {
75 _beg = beg;
76 }
77 else if (beg > this->getEnd())
78 {
79 ID3D_WARNING( "WindowedReader::setBeg() failed, [beg, _end] = " <<
80 beg << ", " << this->getEnd() << "]" );
81 }
82 else
83 {
84 ID3D_WARNING( "WindowedReader::setBeg() failed, [beg, _beg] = " <<
85 beg << ", " << this->getBeg() << "]" );
86 }
87 return _beg;
88}
89
90ID3_Reader::pos_type io::WindowedReader::setEnd(pos_type end)
91{
92 // make sure the position we want to set to isn't beforen the current
93 // beginning position or the superclass's end position
94 if (this->getBeg() <= end && end <= _reader.getEnd())
95 {
96 _end = end;
97 }
98 else
99 {
100 ID3D_WARNING( "WindowedReader::setEnd() failed, end = " << end );
101 ID3D_WARNING( "WindowedReader::setEnd() failed, beg = " <<
102 this->getBeg() );
103 ID3D_WARNING( "WindowedReader::setEnd() failed, super.end = " <<
104 _reader.getEnd() );
105
106 }
107 return _end;
108}
109
110ID3_Reader::int_type io::WindowedReader::readChar()
111{
112 int_type ch = END_OF_READER;
113 if (this->inWindow())
114 {
115 ch = _reader.readChar();
116 }
117 else
118 {
119 ID3D_WARNING( "io::WindowedReader::readChar: not in window, " <<
120 "pos = " << this->getCur() << ", window = [" <<
121 this->getBeg() << ", " << this->getEnd() << "]");
122 }
123 return ch;
124}
125
126ID3_Reader::int_type io::WindowedReader::peekChar()
127{
128 int_type ch = END_OF_READER;
129 if (this->inWindow())
130 {
131 ch = _reader.peekChar();
132 }
133 return ch;
134}
135
136ID3_Reader::size_type io::WindowedReader::readChars(char_type buf[], size_type len)
137{
138 pos_type cur = this->getCur();
139 size_type size = 0;
140 if (this->inWindow(cur))
141 {
142 size = _reader.readChars(buf, min<size_type>(len, _end - cur));
143 }
144 return size;
145}
146
147ID3_Reader::size_type io::CharReader::readChars(char_type buf[], size_type len)
148{
149 size_type numChars = 0;
150 ID3D_NOTICE( "CharReader::readChars(): len = " << len );
151 for (; numChars < len; ++numChars)
152 {
153 if (this->atEnd())
154 {
155 break;
156 }
157 char_type ch = this->readChar();
158 if (buf != NULL)
159 {
160 buf[numChars] = ch;
161 }
162 }
163 ID3D_NOTICE( "CharReader::readChars(): numChars = " << len );
164 return numChars;
165}
166
167ID3_Reader::int_type io::LineFeedReader::readChar()
168{
169 if (this->atEnd())
170 {
171 return END_OF_READER;
172 }
173 char_type ch = _reader.readChar();
174 if (ch == 0x0D && this->peekChar() == 0x0A)
175 {
176 ID3D_NOTICE( "LineFeedReader::readChar(): found CRLF at pos " <<
177 this->getCur() );
178 ch = _reader.readChar();
179 }
180 return ch;
181};
182
183ID3_Reader::int_type io::UnsyncedReader::readChar()
184{
185 if (this->atEnd())
186 {
187 return END_OF_READER;
188 }
189 char_type ch = _reader.readChar();
190 if (ch == 0xFF && this->peekChar() == 0x00)
191 {
192 ID3D_NOTICE( "UnsyncedReader::readChar(): found sync at pos " <<
193 this->getCur() );
194 _reader.readChar();
195 }
196 return ch;
197}
198
199io::CompressedReader::CompressedReader(ID3_Reader& reader, size_type newSize)
200 : _uncompressed(new char_type[newSize])
201{
202 size_type oldSize = reader.remainingBytes();
203
204 BString binary = readBinary(reader, oldSize);
205
206 ::uncompress(_uncompressed,
207 reinterpret_cast<luint*>(&newSize),
208 reinterpret_cast<const uchar*>(binary.data()),
209 oldSize);
210 this->setBuffer(_uncompressed, newSize);
211}
212
213io::CompressedReader::~CompressedReader()
214{
215 delete [] _uncompressed;
216}
217
218ID3_Writer::int_type io::UnsyncedWriter::writeChar(char_type ch)
219{
220 if (_last == 0xFF && (ch == 0x00 || ch >= 0xE0))
221 {
222 _writer.writeChar('\0');
223 _numSyncs++;
224 }
225 _last = _writer.writeChar(ch);
226 return _last;
227}
228
229void io::UnsyncedWriter::flush()
230{
231 if (_last == 0xFF)
232 {
233 _last = _writer.writeChar('\0');
234 _numSyncs++;
235 }
236 _writer.flush();
237}
238
240io::UnsyncedWriter::writeChars(const char_type buf[], size_type len)
241{
242 pos_type beg = this->getCur();
243 ID3D_NOTICE( "UnsyncedWriter::writeChars(): len = " << len );
244 for (size_t i = 0; i < len; ++i)
245 {
246 if (this->atEnd())
247 {
248 break;
249 }
250 this->writeChar(buf[i]);
251 }
252 size_type numChars = this->getCur() - beg;
253 ID3D_NOTICE( "CharWriter::writeChars(): numChars = " << numChars );
254 return numChars;
255}
256
257void io::CompressedWriter::flush()
258{
259 if (_data.size() == 0)
260 {
261 return;
262 }
263 const char_type* data = reinterpret_cast<const char_type*>(_data.data());
264 size_type dataSize = _data.size();
265 _origSize = dataSize;
266 // The zlib documentation specifies that the destination size needs to
267 // be an unsigned long at least 0.1% larger than the source buffer,
268 // plus 12 bytes
269 unsigned long newDataSize = dataSize + (dataSize / 10) + 12;
270 char_type* newData = new char_type[newDataSize];
271 if (::compress(newData, &newDataSize, data, dataSize) != Z_OK)
272 {
273 // log this
274 ID3D_WARNING("io::CompressedWriter: error compressing");
275 _writer.writeChars(data, dataSize);
276 }
277 else if (newDataSize < dataSize)
278 {
279 ID3D_NOTICE("io::CompressedWriter: compressed size = " << newDataSize << ", original size = " << dataSize );
280 _writer.writeChars(newData, newDataSize);
281 }
282 else
283 {
284 ID3D_NOTICE("io::CompressedWriter: no compression!compressed size = " << newDataSize << ", original size = " << dataSize );
285 _writer.writeChars(data, dataSize);
286 }
287 delete [] newData;
288 _data.erase();
289}
290
292io::CompressedWriter::writeChars(const char_type buf[], size_type len)
293{
294 ID3D_NOTICE("io::CompressedWriter: writing chars: " << len );
295 _data.append(buf, len);
296 return len;
297}
298
uint32 pos_type
Definition reader.h:38
virtual size_type remainingBytes()
Definition reader.h:109
int16 int_type
Definition reader.h:40
uint32 size_type
Definition reader.h:36
int16 int_type
Definition writer.h:40
uint32 size_type
Definition writer.h:36
#define NULL
Definition globals.h:743
long unsigned int luint
Definition globals.h:115
unsigned char uchar
Definition globals.h:114
const T & min(const T &a, const T &b)
Definition utils.h:51