id3lib  3.8.3
frame_parse.cpp
Go to the documentation of this file.
1 // $Id: frame_parse.cpp,v 1.34 2002/07/06 13:53:18 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 #include "frame_impl.h"
32 #include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"
33 
34 using namespace dami;
35 
36 namespace
37 {
38  bool parseFields(ID3_Reader& rdr, ID3_FrameImpl& frame)
39  {
40  int iLoop;
41  int iFields;
42  io::ExitTrigger et(rdr);
43  ID3_TextEnc enc = ID3TE_ASCII; // set the default encoding
44  ID3_V2Spec spec = frame.GetSpec();
45  // parse the frame's fields
46  iFields = frame.NumFields();
47  ID3D_NOTICE( "ID3_FrameImpl::Parse(): num_fields = " << iFields );
48  iLoop = 0;
49  for (ID3_FrameImpl::iterator fi = frame.begin(); fi != frame.end(); ++fi)
50  {
51  ID3_Field* fp = *fi;
52  ++iLoop;
53 
54  if (rdr.atEnd())
55  {
56  // there's no remaining data to parse!
57  ID3D_WARNING( "ID3_FrameImpl::Parse(): out of data at postion " <<
58  rdr.getCur() );
59  if (iLoop == iFields)
60  {
61  //if we are at the last field, (the 'data' field) it's apparently
62  //an empty tag used for filling up padding, it's no problem
63  //break will set the current 'cursor' to the right spot outside the for loop
64  break;
65  }
66  return false;
67  }
68 
69  if (NULL == fp)
70  {
71  // Ack! Why is the field NULL? Log this...
72  ID3D_WARNING( "ID3_FrameImpl::Parse(): field is null" );
73  continue;
74  }
75 
76  if (!fp->InScope(spec))
77  {
78  ID3D_NOTICE( "ID3_FrameImpl::Parse(): field is not in scope" );
79  // continue with the rest of the fields
80  continue;
81  }
82 
83  ID3D_NOTICE( "ID3_FrameImpl::Parse(): setting enc to " << enc );
84  fp->SetEncoding(enc);
85  ID3_Reader::pos_type beg = rdr.getCur();
86  et.setExitPos(beg);
87  ID3D_NOTICE( "ID3_FrameImpl::Parse(): parsing field, cur = " << beg );
88  ID3D_NOTICE( "ID3_FrameImpl::Parse(): parsing field, end = " <<
89  rdr.getEnd() );
90  if (!fp->Parse(rdr) || rdr.getCur() == beg)
91  {
92  // nothing to parse! ack! parse error...
93  ID3D_WARNING( "ID3_FrameImpl::Parse(): no data parsed, bad parse" );
94  return false;
95  }
96 
97  if (fp->GetID() == ID3FN_TEXTENC)
98  {
99  enc = static_cast<ID3_TextEnc>(fp->Get());
100  ID3D_NOTICE( "ID3_FrameImpl::Parse(): found encoding = " << enc );
101  }
102  }
103  et.setExitPos(rdr.getCur());
104 
105  return true;
106  }
107 };
108 
110 {
111  io::ExitTrigger et(reader);
112  ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getBeg() = " << reader.getBeg() );
113  ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getCur() = " << reader.getCur() );
114  ID3D_NOTICE( "ID3_FrameImpl::Parse(): reader.getEnd() = " << reader.getEnd() );
115  ID3_Reader::pos_type beg = reader.getCur();
116 
117  if (!_hdr.Parse(reader) || reader.getCur() == beg)
118  {
119  ID3D_WARNING( "ID3_FrameImpl::Parse(): no header to parse" );
120  return false;
121  }
122  ID3D_NOTICE( "ID3_FrameImpl::Parse(): after hdr, getCur() = " << reader.getCur() );
123  ID3D_NOTICE( "ID3_FrameImpl::Parse(): found frame! id = " << _hdr.GetTextID() );
124 
125  // data is the part of the frame buffer that appears after the header
126  const size_t dataSize = _hdr.GetDataSize();
127  ID3D_NOTICE( "ID3_FrameImpl::Parse(): dataSize = " << dataSize );
128  if (reader.getEnd() < beg + dataSize)
129  {
130  ID3D_WARNING( "ID3_FrameImpl::Parse(): not enough data to parse frame" );
131  return false;
132  }
133  io::WindowedReader wr(reader, dataSize);
134  ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getBeg() = " << wr.getBeg() );
135  ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getCur() = " << wr.getCur() );
136  ID3D_NOTICE( "ID3_FrameImpl::Parse(): window getEnd() = " << wr.getEnd() );
137 
138  unsigned long origSize = 0;
139  if (_hdr.GetCompression())
140  {
141  origSize = io::readBENumber(reader, sizeof(uint32));
142  ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is compressed, origSize = " << origSize );
143  }
144 
145  if (_hdr.GetEncryption())
146  {
147  char ch = wr.readChar();
148  this->SetEncryptionID(ch);
149  ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is encrypted, encryption_id = " << (int) ch );
150  }
151 
152  if (_hdr.GetGrouping())
153  {
154  char ch = wr.readChar();
155  this->SetGroupingID(ch);
156  ID3D_NOTICE( "ID3_FrameImpl::Parse(): frame is encrypted, grouping_id = " << (int) ch );
157  }
158 
159  // set the type of frame based on the parsed header
160  this->_ClearFields();
161  this->_InitFields();
162 
163  bool success = false;
164  // expand out the data if it's compressed
165  if (!_hdr.GetCompression())
166  {
167  success = parseFields(wr, *this);
168  }
169  else
170  {
171  io::CompressedReader csr(wr, origSize);
172  success = parseFields(csr, *this);
173  }
174  et.setExitPos(wr.getCur());
175 
176  _changed = false;
177  return true;
178 }
179 
The representative class of an ID3v2 field.
Definition: field.h:37
virtual uint32 Get() const =0
Returns the value of the integer field.
virtual ID3_FieldID GetID() const =0
virtual bool Parse(ID3_Reader &)=0
virtual bool SetEncoding(ID3_TextEnc enc)=0
virtual bool InScope(ID3_V2Spec spec) const =0
bool Parse(ID3_Reader &)
size_t NumFields() const
Definition: frame_impl.cpp:167
iterator end()
Definition: frame_impl.h:117
ID3_V2Spec GetSpec() const
Definition: frame_impl.cpp:145
Fields::iterator iterator
Definition: frame_impl.h:46
iterator begin()
Definition: frame_impl.h:116
virtual pos_type getCur()=0
Return the current position in the reader.
virtual bool atEnd()
Definition: reader.h:125
virtual pos_type getEnd()
Return the ending position in the reader.
Definition: reader.h:51
uint32 pos_type
Definition: reader.h:38
virtual pos_type getBeg()
Return the beginning position in the reader.
Definition: reader.h:48
#define NULL
Definition: globals.h:743
@ ID3FN_TEXTENC
Text encoding (unicode or ASCII)
Definition: globals.h:200
ID3_TextEnc
Enumeration of the types of text encodings: ascii or unicode.
Definition: globals.h:138
@ ID3TE_ASCII
Definition: globals.h:145
ID3_V2Spec
Definition: globals.h:162
Definition: tag_impl.h:42