id3lib 3.8.3
|
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