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 
36 using namespace dami;
37 
38 void 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 
69 ID3_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 
90 ID3_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 
110 ID3_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 
126 ID3_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 
136 ID3_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 
147 ID3_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 
167 ID3_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 
183 ID3_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 
199 io::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 
213 io::CompressedReader::~CompressedReader()
214 {
215  delete [] _uncompressed;
216 }
217 
218 ID3_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 
229 void io::UnsyncedWriter::flush()
230 {
231  if (_last == 0xFF)
232  {
233  _last = _writer.writeChar('\0');
234  _numSyncs++;
235  }
236  _writer.flush();
237 }
238 
240 io::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 
257 void 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 
292 io::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
Definition: tag_impl.h:42