id3lib
3.8.3
|
00001 // $Id: frame_parse.cpp,v 1.34 2002/07/06 13:53:18 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 #include "frame_impl.h" 00032 #include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h" 00033 00034 using namespace dami; 00035 00036 namespace 00037 { 00038 bool parseFields(ID3_Reader& rdr, ID3_FrameImpl& frame) 00039 { 00040 int iLoop; 00041 int iFields; 00042 io::ExitTrigger et(rdr); 00043 ID3_TextEnc enc = ID3TE_ASCII; // set the default encoding 00044 ID3_V2Spec spec = frame.GetSpec(); 00045 // parse the frame's fields 00046 iFields = frame.NumFields(); 00047 ID3D_NOTICE( "ID3_FrameImpl::Parse(): num_fields = " << iFields ); 00048 iLoop = 0; 00049 for (ID3_FrameImpl::iterator fi = frame.begin(); fi != frame.end(); ++fi) 00050 { 00051 ID3_Field* fp = *fi; 00052 ++iLoop; 00053 00054 if (rdr.atEnd()) 00055 { 00056 // there's no remaining data to parse! 00057 ID3D_WARNING( "ID3_FrameImpl::Parse(): out of data at postion " << 00058 rdr.getCur() ); 00059 if (iLoop == iFields) 00060 { 00061 //if we are at the last field, (the 'data' field) it's apparently 00062 //an empty tag used for filling up padding, it's no problem 00063 //break will set the current 'cursor' to the right spot outside the for loop 00064 break; 00065 } 00066 return false; 00067 } 00068 00069 if (NULL == fp) 00070 { 00071 // Ack! Why is the field NULL? Log this... 00072 ID3D_WARNING( "ID3_FrameImpl::Parse(): field is null" ); 00073 continue; 00074 } 00075 00076 if (!fp->InScope(spec)) 00077 { 00078 ID3D_NOTICE( "ID3_FrameImpl::Parse(): field is not in scope" ); 00079 // continue with the rest of the fields 00080 continue; 00081 } 00082 00083 ID3D_NOTICE( "ID3_FrameImpl::Parse(): setting enc to " << enc ); 00084 fp->SetEncoding(enc); 00085 ID3_Reader::pos_type beg = rdr.getCur(); 00086 et.setExitPos(beg); 00087 ID3D_NOTICE( "ID3_FrameImpl::Parse(): parsing field, cur = " << beg ); 00088 ID3D_NOTICE( "ID3_FrameImpl::Parse(): parsing field, end = " << 00089 rdr.getEnd() ); 00090 if (!fp->Parse(rdr) || rdr.getCur() == beg) 00091 { 00092 // nothing to parse! ack! parse error... 00093 ID3D_WARNING( "ID3_FrameImpl::Parse(): no data parsed, bad parse" ); 00094 return false; 00095 } 00096 00097 if (fp->GetID() == ID3FN_TEXTENC) 00098 { 00099 enc = static_cast<ID3_TextEnc>(fp->Get()); 00100 ID3D_NOTICE( "ID3_FrameImpl::Parse(): found encoding = " << enc ); 00101 } 00102 } 00103 et.setExitPos(rdr.getCur()); 00104 00105 return true; 00106 } 00107 }; 00108 00109 bool ID3_FrameImpl::Parse(ID3_Reader& reader) 00110 { 00111 io::ExitTrigger et(reader); 00112 ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getBeg() = " << reader.getBeg() ); 00113 ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getCur() = " << reader.getCur() ); 00114 ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getEnd() = " << reader.getEnd() ); 00115 ID3_Reader::pos_type beg = reader.getCur(); 00116 00117 if (!_hdr.Parse(reader) || reader.getCur() == beg) 00118 { 00119 ID3D_WARNING( "ID3_FrameImpl::Parse(): no header to parse" ); 00120 return false; 00121 } 00122 ID3D_NOTICE( "ID3_FrameImpl::Parse(): after hdr, getCur() = " << reader.getCur() ); 00123 ID3D_NOTICE( "ID3_FrameImpl::Parse(): found frame! id = " << _hdr.GetTextID() ); 00124 00125 // data is the part of the frame buffer that appears after the header 00126 const size_t dataSize = _hdr.GetDataSize(); 00127 ID3D_NOTICE( "ID3_FrameImpl::Parse(): dataSize = " << dataSize ); 00128 if (reader.getEnd() < beg + dataSize) 00129 { 00130 ID3D_WARNING( "ID3_FrameImpl::Parse(): not enough data to parse frame" ); 00131 return false; 00132 } 00133 io::WindowedReader wr(reader, dataSize); 00134 ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getBeg() = " << wr.getBeg() ); 00135 ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getCur() = " << wr.getCur() ); 00136 ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getEnd() = " << wr.getEnd() ); 00137 00138 unsigned long origSize = 0; 00139 if (_hdr.GetCompression()) 00140 { 00141 origSize = io::readBENumber(reader, sizeof(uint32)); 00142 ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is compressed, origSize = " << origSize ); 00143 } 00144 00145 if (_hdr.GetEncryption()) 00146 { 00147 char ch = wr.readChar(); 00148 this->SetEncryptionID(ch); 00149 ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is encrypted, encryption_id = " << (int) ch ); 00150 } 00151 00152 if (_hdr.GetGrouping()) 00153 { 00154 char ch = wr.readChar(); 00155 this->SetGroupingID(ch); 00156 ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is encrypted, grouping_id = " << (int) ch ); 00157 } 00158 00159 // set the type of frame based on the parsed header 00160 this->_ClearFields(); 00161 this->_InitFields(); 00162 00163 bool success = false; 00164 // expand out the data if it's compressed 00165 if (!_hdr.GetCompression()) 00166 { 00167 success = parseFields(wr, *this); 00168 } 00169 else 00170 { 00171 io::CompressedReader csr(wr, origSize); 00172 success = parseFields(csr, *this); 00173 } 00174 et.setExitPos(wr.getCur()); 00175 00176 _changed = false; 00177 return true; 00178 } 00179