src/io_decorators.cpp

Go to the documentation of this file.
00001 // $Id: io_decorators.cpp,v 1.4 2002/07/02 22:13:40 t1mpy Exp $
00002 
00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
00004 // Copyright 1999, 2000  Scott Thomas Haug
00005 
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Library General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or (at your
00009 // option) any later version.
00010 //
00011 // This library is distributed in the hope that it will be useful, but WITHOUT
00012 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014 // License for more details.
00015 //
00016 // You should have received a copy of the GNU Library General Public License
00017 // along with this library; if not, write to the Free Software Foundation,
00018 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 
00020 // The id3lib authors encourage improvements and optimisations to be sent to
00021 // the id3lib coordinator.  Please see the README file for details on where to
00022 // send such submissions.  See the AUTHORS file for a list of people who have
00023 // contributed to id3lib.  See the ChangeLog file for a list of changes to
00024 // id3lib.  These files are distributed with id3lib at
00025 // http://download.sourceforge.net/id3lib/
00026 
00027 #if defined HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 
00031 
00032 
00033 #include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"
00034 #include "zlib.h"
00035 
00036 using namespace dami;
00037 
00038 void io::WindowedReader::setWindow(pos_type beg, size_type size)
00039 {
00040   ID3D_NOTICE( "WindowedReader::setWindow() [beg, size] = [" << 
00041                this->getBeg() << ", " << size << "]" );
00042   pos_type cur = this->getCur();
00043   
00044   // reset the end marker so as to avoid errors
00045   this->setEnd(_reader.getEnd());
00046   
00047   // set the beginning marker
00048   this->setBeg(beg);
00049   
00050   // since the characters might be more than a byte in size, we need to 
00051   // manually get all the chars to set the window appropriately
00052   this->setCur(beg);
00053   ID3D_NOTICE( "WindowedReader::setWindow(): after setCur(beg), cur = "<<
00054                this->getCur() );
00055   
00056   this->skipChars(size);
00057   ID3D_NOTICE( "WindowedReader::setWindow(): after skipChars, cur = " <<
00058                this->getCur() );
00059   
00060   this->setEnd(this->getCur());
00061   
00062   ID3D_NOTICE( "WindowedReader::setWindow() [beg, cur, end] = [" << this->getBeg() << ", " << this->getCur() << ", " << this->getEnd() << "]" );
00063   
00064   
00065   // reset the stream
00066   this->setCur(cur);
00067 }
00068 
00069 ID3_Reader::pos_type io::WindowedReader::setBeg(pos_type beg)
00070 {
00071   // make sure the position we want to set to isn't past the current
00072   // end position or the superclass's beginning position
00073   if (beg <= this->getEnd() && beg >= _reader.getBeg())
00074   {
00075     _beg = beg;
00076   }
00077   else if (beg > this->getEnd())
00078   {
00079     ID3D_WARNING( "WindowedReader::setBeg() failed, [beg, _end] = " << 
00080                   beg << ", " << this->getEnd() << "]" );
00081   }
00082   else
00083   {
00084     ID3D_WARNING( "WindowedReader::setBeg() failed, [beg, _beg] = " << 
00085                   beg << ", " << this->getBeg() << "]" );
00086   }
00087   return _beg;
00088 }
00089 
00090 ID3_Reader::pos_type io::WindowedReader::setEnd(pos_type end)
00091 {
00092   // make sure the position we want to set to isn't beforen the current
00093   // beginning position or the superclass's end position
00094   if (this->getBeg() <= end && end <= _reader.getEnd())
00095   {
00096     _end = end;
00097   }
00098   else
00099   {
00100     ID3D_WARNING( "WindowedReader::setEnd() failed, end = " << end );
00101     ID3D_WARNING( "WindowedReader::setEnd() failed, beg = " << 
00102                   this->getBeg() );
00103     ID3D_WARNING( "WindowedReader::setEnd() failed, super.end = " << 
00104                   _reader.getEnd() );
00105     
00106   }
00107   return _end;
00108 }
00109 
00110 ID3_Reader::int_type io::WindowedReader::readChar()
00111 {
00112   int_type ch = END_OF_READER;
00113   if (this->inWindow())
00114   {
00115     ch = _reader.readChar();
00116   }
00117   else
00118   {
00119     ID3D_WARNING( "io::WindowedReader::readChar: not in window, " << 
00120                   "pos = " << this->getCur() << ", window = [" << 
00121                   this->getBeg() << ", " << this->getEnd() << "]");
00122   }
00123   return ch;
00124 }
00125 
00126 ID3_Reader::int_type io::WindowedReader::peekChar()
00127 {
00128   int_type ch = END_OF_READER;
00129   if (this->inWindow())
00130   {
00131     ch = _reader.peekChar();
00132   }
00133   return ch;
00134 }
00135 
00136 ID3_Reader::size_type io::WindowedReader::readChars(char_type buf[], size_type len)
00137 {
00138   pos_type cur = this->getCur();
00139   size_type size = 0;
00140   if (this->inWindow(cur))
00141   {
00142     size = _reader.readChars(buf, min<size_type>(len, _end - cur));
00143   }
00144   return size;
00145 }
00146 
00147 ID3_Reader::size_type io::CharReader::readChars(char_type buf[], size_type len)
00148 {
00149   size_type numChars = 0;
00150   ID3D_NOTICE( "CharReader::readChars(): len = " << len );
00151   for (; numChars < len; ++numChars)
00152   {
00153     if (this->atEnd())
00154     {
00155       break;
00156     }
00157     char_type ch = this->readChar();
00158     if (buf != NULL)
00159     {
00160       buf[numChars] = ch;
00161     }
00162   }
00163   ID3D_NOTICE( "CharReader::readChars(): numChars = " << len );
00164   return numChars;
00165 }
00166 
00167 ID3_Reader::int_type io::LineFeedReader::readChar()
00168 {
00169   if (this->atEnd())
00170   {
00171     return END_OF_READER;
00172   }
00173   char_type ch = _reader.readChar();
00174   if (ch == 0x0D && this->peekChar() == 0x0A)
00175   {
00176     ID3D_NOTICE( "LineFeedReader::readChar(): found CRLF at pos " << 
00177                  this->getCur() );
00178     ch = _reader.readChar();
00179   }
00180   return ch;
00181 };
00182 
00183 ID3_Reader::int_type io::UnsyncedReader::readChar()
00184 {
00185   if (this->atEnd())
00186   {
00187     return END_OF_READER;
00188   }
00189   char_type ch = _reader.readChar();
00190   if (ch == 0xFF && this->peekChar() == 0x00)
00191   {
00192     ID3D_NOTICE( "UnsyncedReader::readChar(): found sync at pos " << 
00193                  this->getCur() );
00194     _reader.readChar();
00195   }
00196   return ch;
00197 }
00198 
00199 io::CompressedReader::CompressedReader(ID3_Reader& reader, size_type newSize)
00200   : _uncompressed(new char_type[newSize])
00201 {
00202   size_type oldSize = reader.remainingBytes();
00203   
00204   BString binary = readBinary(reader, oldSize);
00205   
00206   ::uncompress(_uncompressed,
00207                reinterpret_cast<luint*>(&newSize),
00208                reinterpret_cast<const uchar*>(binary.data()),
00209                oldSize);
00210   this->setBuffer(_uncompressed, newSize);
00211 }
00212 
00213 io::CompressedReader::~CompressedReader()
00214 { 
00215   delete [] _uncompressed; 
00216 }
00217 
00218 ID3_Writer::int_type io::UnsyncedWriter::writeChar(char_type ch)
00219 {
00220   if (_last == 0xFF && (ch == 0x00 || ch >= 0xE0))
00221   {
00222     _writer.writeChar('\0');
00223     _numSyncs++;
00224   }
00225   _last = _writer.writeChar(ch);
00226   return _last;
00227 }
00228 
00229 void io::UnsyncedWriter::flush()
00230 {
00231   if (_last == 0xFF)
00232   {
00233     _last = _writer.writeChar('\0');
00234     _numSyncs++;
00235   }
00236   _writer.flush();
00237 }
00238 
00239 ID3_Writer::size_type 
00240 io::UnsyncedWriter::writeChars(const char_type buf[], size_type len)
00241 {
00242   pos_type beg = this->getCur();
00243   ID3D_NOTICE( "UnsyncedWriter::writeChars(): len = " << len );
00244   for (size_t i = 0; i < len; ++i)
00245   {
00246     if (this->atEnd())
00247     {
00248       break;
00249     }
00250     this->writeChar(buf[i]);
00251   }
00252   size_type numChars = this->getCur() - beg;
00253   ID3D_NOTICE( "CharWriter::writeChars(): numChars = " << numChars );
00254   return numChars;
00255 }
00256 
00257 void io::CompressedWriter::flush()
00258 {
00259   if (_data.size() == 0)
00260   {
00261     return;
00262   }
00263   const char_type* data = reinterpret_cast<const char_type*>(_data.data());
00264   size_type dataSize = _data.size();
00265   _origSize = dataSize;
00266   // The zlib documentation specifies that the destination size needs to
00267   // be an unsigned long at least 0.1% larger than the source buffer,
00268   // plus 12 bytes
00269   unsigned long newDataSize = dataSize + (dataSize / 10) + 12;
00270   char_type* newData = new char_type[newDataSize];
00271   if (::compress(newData, &newDataSize, data, dataSize) != Z_OK)
00272   {
00273     // log this
00274     ID3D_WARNING("io::CompressedWriter: error compressing");
00275     _writer.writeChars(data, dataSize);
00276   }
00277   else if (newDataSize < dataSize)
00278   {
00279     ID3D_NOTICE("io::CompressedWriter: compressed size = " << newDataSize << ", original size = " << dataSize ); 
00280     _writer.writeChars(newData, newDataSize);
00281   }
00282   else
00283   {
00284     ID3D_NOTICE("io::CompressedWriter: no compression!compressed size = " << newDataSize << ", original size = " << dataSize ); 
00285     _writer.writeChars(data, dataSize);
00286   }
00287   delete [] newData;
00288   _data.erase();
00289 }
00290 
00291 ID3_Writer::size_type 
00292 io::CompressedWriter::writeChars(const char_type buf[], size_type len)
00293 { 
00294   ID3D_NOTICE("io::CompressedWriter: writing chars: " << len );
00295   _data.append(buf, len);
00296   return len;
00297 }
00298 

Generated on Mon Aug 20 17:48:46 2007 for id3lib by  doxygen 1.5.2