<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>src/tag_parse.cpp Source File</title> <link href="id3lib.css" rel="stylesheet" type="text/css"> </head><body bgcolor="#ffffff"> <!-- Generated by Doxygen 1.2.12 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="namespaces.html">Namespace List</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="namespacemembers.html">Namespace Members</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> </center> <hr><h1>src/tag_parse.cpp</h1><a href="tag__parse_8cpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 <font class="comment">// $Id: tag_parse.cpp,v 1.38 2000/10/29 01:37:29 eldamitri Exp $</font> 00002 00003 <font class="comment">// id3lib: a C++ library for creating and manipulating id3v1/v2 tags</font> 00004 <font class="comment">// Copyright 1999, 2000 Scott Thomas Haug</font> 00005 00006 <font class="comment">// This library is free software; you can redistribute it and/or modify it</font> 00007 <font class="comment">// under the terms of the GNU Library General Public License as published by</font> 00008 <font class="comment">// the Free Software Foundation; either version 2 of the License, or (at your</font> 00009 <font class="comment">// option) any later version.</font> 00010 <font class="comment">//</font> 00011 <font class="comment">// This library is distributed in the hope that it will be useful, but WITHOUT</font> 00012 <font class="comment">// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or</font> 00013 <font class="comment">// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public</font> 00014 <font class="comment">// License for more details.</font> 00015 <font class="comment">//</font> 00016 <font class="comment">// You should have received a copy of the GNU Library General Public License</font> 00017 <font class="comment">// along with this library; if not, write to the Free Software Foundation,</font> 00018 <font class="comment">// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</font> 00019 00020 <font class="comment">// The id3lib authors encourage improvements and optimisations to be sent to</font> 00021 <font class="comment">// the id3lib coordinator. Please see the README file for details on where to</font> 00022 <font class="comment">// send such submissions. See the AUTHORS file for a list of people who have</font> 00023 <font class="comment">// contributed to id3lib. See the ChangeLog file for a list of changes to</font> 00024 <font class="comment">// id3lib. These files are distributed with id3lib at</font> 00025 <font class="comment">// http://download.sourceforge.net/id3lib/</font> 00026 00027 <font class="preprocessor">#if defined HAVE_CONFIG_H</font> 00028 <font class="preprocessor"></font><font class="preprocessor">#include <config.h></font> <font class="comment">// Must include before zlib.h to compile on WinCE</font> 00029 <font class="preprocessor">#endif</font> 00030 <font class="preprocessor"></font> 00031 00032 00033 <font class="preprocessor">#include <zlib.h></font> 00034 <font class="preprocessor">#include <string.h></font> 00035 <font class="preprocessor">#include <memory.h></font> 00036 00037 <font class="preprocessor">#include "<a class="code" href="tag__impl_8h.html">tag_impl.h</a>"</font> 00038 <font class="preprocessor">#include "utils.h"</font> 00039 <font class="preprocessor">#include "io_decorators.h"</font> 00040 <font class="preprocessor">#include "io_helpers.h"</font> 00041 <font class="preprocessor">#include "io_strings.h"</font> 00042 <font class="preprocessor">#include "<a class="code" href="readers_8h.html">readers.h</a>"</font> 00043 00044 <font class="keyword">using</font> <font class="keyword">namespace </font>dami; 00045 00046 <font class="keyword">namespace</font> 00047 <font class="keyword"></font>{ 00048 <font class="keywordtype">bool</font> parseFrames(<a class="code" href="class_i_d3___tag_impl.html">ID3_TagImpl</a>& tag, <a class="code" href="class_i_d3___reader.html">ID3_Reader</a>& rdr) 00049 { 00050 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> beg = rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>(); 00051 io::ExitTrigger et(rdr, beg); 00052 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> last_pos = beg; 00053 size_t totalSize = 0; 00054 size_t frameSize = 0; 00055 <font class="keywordflow">while</font> (!rdr.<a class="code" href="class_i_d3___reader.html#a11">atEnd</a>() && rdr.<a class="code" href="class_i_d3___reader.html#a6">peekChar</a>() != <font class="charliteral">'\0'</font>) 00056 { 00057 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): rdr.getBeg() = "</font> << rdr.<a class="code" href="class_i_d3___reader.html#a1">getBeg</a>() ); 00058 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): rdr.getCur() = "</font> << rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>() ); 00059 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): rdr.getEnd() = "</font> << rdr.<a class="code" href="class_i_d3___reader.html#a2">getEnd</a>() ); 00060 last_pos = rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>(); 00061 <a class="code" href="class_i_d3___frame.html">ID3_Frame</a>* f = <font class="keyword">new</font> <a class="code" href="class_i_d3___frame.html">ID3_Frame</a>; 00062 f-><a class="code" href="class_i_d3___frame.html#a16">SetSpec</a>(tag.<a class="code" href="class_i_d3___tag_impl.html#a32">GetSpec</a>()); 00063 <font class="keywordtype">bool</font> goodParse = f-><a class="code" href="class_i_d3___frame.html#a12">Parse</a>(rdr); 00064 frameSize = rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>() - last_pos; 00065 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): frameSize = "</font> << frameSize ); 00066 totalSize += frameSize; 00067 00068 <font class="keywordflow">if</font> (frameSize == 0) 00069 { 00070 <font class="comment">// There is a problem. </font> 00071 <font class="comment">// If the frame size is 0, then we can't progress. </font> 00072 ID3D_WARNING( <font class="stringliteral">"id3::v2::parseFrames(): frame size is 0, can't "</font> << 00073 <font class="stringliteral">"continue parsing frames"</font>); 00074 <font class="keyword">delete</font> f; 00075 <font class="comment">// Break for now. </font> 00076 <font class="keywordflow">break</font>; 00077 } 00078 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (!goodParse) 00079 { 00080 <font class="comment">// bad parse! we can't attach this frame.</font> 00081 ID3D_WARNING( <font class="stringliteral">"id3::v2::parseFrames(): bad parse, deleting frame"</font>); 00082 <font class="keyword">delete</font> f; 00083 } 00084 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (f-><a class="code" href="class_i_d3___frame.html#a5">GetID</a>() != <a class="code" href="globals_8h.html#a219a171">ID3FID_METACOMPRESSION</a>) 00085 { 00086 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): attaching non-compressed "</font> << 00087 <font class="stringliteral">"frame"</font>); 00088 <font class="comment">// a good, uncompressed frame. attach away! </font> 00089 tag.<a class="code" href="class_i_d3___tag_impl.html#a16">AttachFrame</a>(f); 00090 } 00091 <font class="keywordflow">else</font> 00092 { 00093 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames(): parsing ID3v2.2.1 "</font> << 00094 <font class="stringliteral">"compressed frame"</font>); 00095 <font class="comment">// hmm. an ID3v2.2.1 compressed frame. It contains 1 or more</font> 00096 <font class="comment">// compressed frames. Uncompress and call parseFrames recursively.</font> 00097 <a class="code" href="class_i_d3___field.html">ID3_Field</a>* fld = f-><a class="code" href="class_i_d3___frame.html#a6">GetField</a>(<a class="code" href="globals_8h.html#a218a74">ID3FN_DATA</a>); 00098 <font class="keywordflow">if</font> (fld) 00099 { 00100 <a class="code" href="class_i_d3___memory_reader.html">ID3_MemoryReader</a> mr(fld-><a class="code" href="class_i_d3___field.html#a23">GetRawBinary</a>(), fld-><a class="code" href="class_i_d3___field.html#a2">BinSize</a>()); 00101 <a class="code" href="class_i_d3___reader.html#s1">ID3_Reader::char_type</a> ch = mr.<a class="code" href="class_i_d3___reader.html#a5">readChar</a>(); 00102 <font class="keywordflow">if</font> (ch != <font class="charliteral">'z'</font>) 00103 { 00104 <font class="comment">// unknown compression method </font> 00105 ID3D_WARNING( <font class="stringliteral">"id3::v2::parseFrames(): unknown compression id "</font> << 00106 <font class="stringliteral">" = '"</font> << ch << <font class="stringliteral">"'"</font> ); 00107 } 00108 <font class="keywordflow">else</font> 00109 { 00110 <a class="code" href="sized__types_8h.html#a4">uint32</a> newSize = io::readBENumber(mr, <font class="keyword">sizeof</font>(<a class="code" href="sized__types_8h.html#a4">uint32</a>)); 00111 size_t oldSize = f-><a class="code" href="class_i_d3___frame.html#a20">GetDataSize</a>() - <font class="keyword">sizeof</font>(uint32) - 1; 00112 io::CompressedReader cr(mr, newSize); 00113 parseFrames(tag, cr); 00114 <font class="keywordflow">if</font> (!cr.atEnd()) 00115 { 00116 <font class="comment">// hmm. it didn't parse the entire uncompressed data. wonder</font> 00117 <font class="comment">// why.</font> 00118 ID3D_WARNING( <font class="stringliteral">"id3::v2::parseFrames(): didn't parse entire "</font> << 00119 <font class="stringliteral">"id3v2.2.1 compressed memory stream"</font>); 00120 } 00121 } 00122 } 00123 <font class="keyword">delete</font> f; 00124 } 00125 et.setExitPos(rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>()); 00126 } 00127 <font class="keywordflow">if</font> (rdr.<a class="code" href="class_i_d3___reader.html#a6">peekChar</a>() == <font class="charliteral">'\0'</font>) 00128 { 00129 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames: done parsing, padding at postion "</font> << 00130 rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>() ); 00131 } 00132 <font class="keywordflow">else</font> 00133 { 00134 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parseFrames: done parsing, [cur, end] = ["</font> << 00135 rdr.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>() << <font class="stringliteral">", "</font> << rdr.<a class="code" href="class_i_d3___reader.html#a2">getEnd</a>() << <font class="stringliteral">"]"</font> ); 00136 } 00137 <font class="keywordflow">return</font> <font class="keyword">true</font>; 00138 } 00139 }; 00140 00141 <font class="keywordtype">bool</font> id3::v2::parse(<a class="code" href="class_i_d3___tag_impl.html">ID3_TagImpl</a>& tag, <a class="code" href="class_i_d3___reader.html">ID3_Reader</a>& reader) 00142 { 00143 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> beg = reader.<a class="code" href="class_i_d3___reader.html#a3">getCur</a>(); 00144 io::ExitTrigger et(reader); 00145 00146 <a class="code" href="class_i_d3___tag_header.html">ID3_TagHeader</a> hdr; 00147 00148 io::WindowedReader wr(reader, <a class="code" href="class_i_d3___tag_header.html#s10s8">ID3_TagHeader::SIZE</a>); 00149 00150 <font class="keywordflow">if</font> (!hdr.<a class="code" href="class_i_d3___tag_header.html#a6">Parse</a>(wr) || wr.getCur() == beg) 00151 { 00152 ID3D_NOTICE( <font class="stringliteral">"id3::v2::parse(): parsing header failes"</font> ); 00153 <font class="keywordflow">return</font> <font class="keyword">false</font>; 00154 } 00155 00156 tag.<a class="code" href="class_i_d3___tag_impl.html#a33">SetSpec</a>(hdr.<a class="code" href="class_i_d3___header.html#a3">GetSpec</a>()); 00157 00158 size_t dataSize = hdr.<a class="code" href="class_i_d3___header.html#a5">GetDataSize</a>(); 00159 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): dataSize = "</font> << dataSize); 00160 00161 wr.setWindow(wr.getCur(), dataSize); 00162 et.setExitPos(wr.getEnd()); 00163 00164 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): data window beg = "</font> << wr.getBeg() ); 00165 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): data window cur = "</font> << wr.getCur() ); 00166 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): data window end = "</font> << wr.getEnd() ); 00167 tag.<a class="code" href="class_i_d3___tag_impl.html#a8">SetExtended</a>(hdr.<a class="code" href="class_i_d3___tag_header.html#a11">GetExtended</a>()); 00168 <font class="keywordflow">if</font> (!hdr.<a class="code" href="class_i_d3___tag_header.html#a9">GetUnsync</a>()) 00169 { 00170 tag.<a class="code" href="class_i_d3___tag_impl.html#a7">SetUnsync</a>(<font class="keyword">false</font>); 00171 parseFrames(tag, wr); 00172 } 00173 <font class="keywordflow">else</font> 00174 { 00175 <font class="comment">// The buffer has been unsynced. It will have to be resynced to be </font> 00176 <font class="comment">// readable. This has to be done a character at a time. </font> 00177 <font class="comment">//</font> 00178 <font class="comment">// The original reader may be reading in characters from a file. Doing</font> 00179 <font class="comment">// this a character at a time is quite slow. To improve performance, read</font> 00180 <font class="comment">// in the entire buffer into a string, then create an UnsyncedReader from</font> 00181 <font class="comment">// the string.</font> 00182 <font class="comment">//</font> 00183 <font class="comment">// It might be better to implement a BufferedReader so that the details</font> 00184 <font class="comment">// of this can be abstracted away behind a class</font> 00185 tag.<a class="code" href="class_i_d3___tag_impl.html#a7">SetUnsync</a>(<font class="keyword">true</font>); 00186 BString raw = io::readAllBinary(wr); 00187 io::BStringReader bsr(raw); 00188 io::UnsyncedReader ur(bsr); 00189 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): unsync beg = "</font> << ur.getBeg() ); 00190 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): unsync cur = "</font> << ur.getCur() ); 00191 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::Parse(ID3_Reader&): unsync end = "</font> << ur.getEnd() ); 00192 00193 <font class="comment">// Now read the UnsyncedReader into another string, and parse the frames</font> 00194 <font class="comment">// from the string. This is done so that 1. the unsynced reader is </font> 00195 <font class="comment">// unsynced exactly once, removing the possibility of multiple unsyncings</font> 00196 <font class="comment">// of the same string, and 2) so that calls to readChars aren't done a </font> 00197 <font class="comment">// character at a time for every call</font> 00198 BString synced = io::readAllBinary(ur); 00199 io::BStringReader sr(synced); 00200 parseFrames(tag, sr); 00201 } 00202 00203 <font class="keywordflow">return</font> <font class="keyword">true</font>; 00204 } 00205 <a name="l00206"></a><a class="code" href="class_i_d3___tag_impl.html#b3">00206</a> <font class="keywordtype">void</font> <a class="code" href="class_i_d3___tag_impl.html#b3">ID3_TagImpl::ParseFile</a>() 00207 { 00208 ifstream file; 00209 <font class="keywordflow">if</font> (<a class="code" href="globals_8h.html#a223a191">ID3E_NoError</a> != openReadableFile(this->GetFileName(), file)) 00210 { 00211 <font class="comment">// log this...</font> 00212 <font class="keywordflow">return</font>; 00213 } 00214 <a class="code" href="class_i_d3___i_f_stream_reader.html">ID3_IFStreamReader</a> ifsr(file); 00215 io::WindowedReader wr(ifsr); 00216 wr.setBeg(wr.getCur()); 00217 00218 _file_tags.<a class="code" href="class_i_d3___flags.html#a7">clear</a>(); 00219 _file_size = getFileSize(file); 00220 00221 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> beg = wr.getBeg(); 00222 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> cur = wr.getCur(); 00223 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> <a class="code" href="class_i_d3___tag_impl.html#a35">end</a> = wr.getEnd(); 00224 00225 <a class="code" href="class_i_d3___reader.html#s2">ID3_Reader::pos_type</a> last = cur; 00226 00227 <font class="keywordflow">if</font> (_tags_to_parse.<a class="code" href="class_i_d3___flags.html#a3">test</a>(<a class="code" href="globals_8h.html#a217a61">ID3TT_ID3V2</a>)) 00228 { 00229 <font class="keywordflow">do</font> 00230 { 00231 last = cur; 00232 <font class="comment">// Parse tags at the beginning of the file first...</font> 00233 <font class="keywordflow">if</font> (id3::v2::parse(*<font class="keyword">this</font>, wr)) 00234 { 00235 _file_tags.<a class="code" href="class_i_d3___flags.html#a5">add</a>(<a class="code" href="globals_8h.html#a217a61">ID3TT_ID3V2</a>); 00236 } 00237 cur = wr.getCur(); 00238 wr.setBeg(cur); 00239 } <font class="keywordflow">while</font> (!wr.atEnd() && cur > last); 00240 } 00241 00242 _prepended_bytes = cur - beg; 00243 00244 cur = wr.setCur(<a class="code" href="class_i_d3___tag_impl.html#a35">end</a>); 00245 <font class="keywordflow">do</font> 00246 { 00247 last = cur; 00248 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): beg = "</font> << wr.getBeg() ); 00249 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): cur = "</font> << wr.getCur() ); 00250 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): end = "</font> << wr.getEnd() ); 00251 <font class="comment">// ...then the tags at the end</font> 00252 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): musicmatch? cur = "</font> << wr.getCur() ); 00253 <font class="keywordflow">if</font> (_tags_to_parse.<a class="code" href="class_i_d3___flags.html#a3">test</a>(<a class="code" href="globals_8h.html#a217a64">ID3TT_MUSICMATCH</a>) && mm::parse(*<font class="keyword">this</font>, wr)) 00254 { 00255 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): musicmatch! cur = "</font> << wr.getCur() ); 00256 _file_tags.<a class="code" href="class_i_d3___flags.html#a5">add</a>(<a class="code" href="globals_8h.html#a217a64">ID3TT_MUSICMATCH</a>); 00257 wr.setEnd(wr.getCur()); 00258 } 00259 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): lyr3v1? cur = "</font> << wr.getCur() ); 00260 <font class="keywordflow">if</font> (_tags_to_parse.<a class="code" href="class_i_d3___flags.html#a3">test</a>(<a class="code" href="globals_8h.html#a217a62">ID3TT_LYRICS3</a>) && lyr3::v1::parse(*<font class="keyword">this</font>, wr)) 00261 { 00262 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): lyr3v1! cur = "</font> << wr.getCur() ); 00263 _file_tags.<a class="code" href="class_i_d3___flags.html#a5">add</a>(<a class="code" href="globals_8h.html#a217a62">ID3TT_LYRICS3</a>); 00264 wr.setEnd(wr.getCur()); 00265 } 00266 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): lyr3v2? cur = "</font> << wr.getCur() ); 00267 <font class="keywordflow">if</font> (_tags_to_parse.<a class="code" href="class_i_d3___flags.html#a3">test</a>(<a class="code" href="globals_8h.html#a217a63">ID3TT_LYRICS3V2</a>) && lyr3::v2::parse(*<font class="keyword">this</font>, wr)) 00268 { 00269 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): lyr3v2! cur = "</font> << wr.getCur() ); 00270 _file_tags.<a class="code" href="class_i_d3___flags.html#a5">add</a>(<a class="code" href="globals_8h.html#a217a60">ID3TT_ID3V1</a>); 00271 wr.setEnd(wr.getCur()); 00272 } 00273 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): id3v1? cur = "</font> << wr.getCur() ); 00274 <font class="keywordflow">if</font> (_tags_to_parse.<a class="code" href="class_i_d3___flags.html#a3">test</a>(<a class="code" href="globals_8h.html#a217a60">ID3TT_ID3V1</a>) && id3::v1::parse(*<font class="keyword">this</font>, wr)) 00275 { 00276 ID3D_NOTICE( <font class="stringliteral">"ID3_TagImpl::ParseFile(): id3v1! cur = "</font> << wr.getCur() ); 00277 wr.setEnd(wr.getCur()); 00278 _file_tags.<a class="code" href="class_i_d3___flags.html#a5">add</a>(<a class="code" href="globals_8h.html#a217a60">ID3TT_ID3V1</a>); 00279 } 00280 cur = wr.getCur(); 00281 } <font class="keywordflow">while</font> (cur != last); 00282 _appended_bytes = <a class="code" href="class_i_d3___tag_impl.html#a35">end</a> - cur; 00283 } </pre></div><hr><address><small>Generated on Thu Jan 3 07:35:56 2002 for id3lib by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.gif" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.12 written by <a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>, © 1997-2001</small></address> </body> </html>