id3lib  3.8.3
tag_impl.cpp
Go to the documentation of this file.
1 // $Id: tag_impl.cpp,v 1.13 2002/09/21 17:23:32 t1mpy Exp $
2 
3 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
4 // Copyright 1999, 2000 Scott Thomas Haug
5 // Copyright 2002 Thijmen Klok (thijmen@id3lib.org)
6 
7 // This library is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU Library General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or (at your
10 // option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with this library; if not, write to the Free Software Foundation,
19 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 
21 // The id3lib authors encourage improvements and optimisations to be sent to
22 // the id3lib coordinator. Please see the README file for details on where to
23 // send such submissions. See the AUTHORS file for a list of people who have
24 // contributed to id3lib. See the ChangeLog file for a list of changes to
25 // id3lib. These files are distributed with id3lib at
26 // http://download.sourceforge.net/id3lib/
27 
28 #if defined HAVE_SYS_PARAM_H
29 #include <sys/param.h>
30 #endif
31 
32 #include "tag_impl.h" //has <stdio.h> "tag.h" "header_tag.h" "frame.h" "field.h" "spec.h" "id3lib_strings.h" "utils.h"
33 //#include "io_helpers.h"
34 #include "io_strings.h"
35 
36 using namespace dami;
37 
39 {
40  io::ExitTrigger et(reader);
41  size_t tagSize = 0;
42  String id = io::readText(reader, ID3_TagHeader::ID_SIZE);
43  String ver = io::readText(reader, 2);
44  char flags = reader.readChar();
45  String size = io::readText(reader, 4);
46 
47  if (id == ID3_TagHeader::ID &&
48  (uchar) ver [0] < 0xFF && (uchar) ver [1] < 0xFF &&
49  (uchar) size[0] < 0x80 && (uchar) size[1] < 0x80 &&
50  (uchar) size[2] < 0x80 && (uchar) size[3] < 0x80)
51  {
52  io::StringReader sr(size);
53  tagSize = io::readUInt28(sr) + ID3_TagHeader::SIZE;
54  }
55  else if (id != ID3_TagHeader::ID)
56  {
57  // clog << "*** IsV2Tag: Not an id3v2 tag header" << endl;
58  }
59  else if ((uchar)ver[0] >= 0xFF)
60  {
61  // clog << "*** IsV2Tag: Major offset" << endl;
62  }
63  else if ((uchar)ver[1] >= 0xFF)
64  {
65  // clog << "*** ISV2Tag: Minor offset" << endl;
66  }
67  else if ((uchar)size[0] >= 0x80)
68  {
69  // clog << "*** ISV2Tag: 1st size offset" << endl;
70  }
71  else if ((uchar)size[1] >= 0x80)
72  {
73  // clog << "*** ISV2Tag: 2nd size offset" << endl;
74  }
75  else if ((uchar)size[2] >= 0x80)
76  {
77  // clog << "*** ISV2Tag: 3rd size offset" << endl;
78  }
79  else if ((uchar)size[3] >= 0x80)
80  {
81  // clog << "*** ISV2Tag: 4th size offset" << endl;
82  }
83  else
84  {
85  // clog << "*** shouldn't get here!" << endl;
86  }
87 
88  return tagSize;
89 }
90 
91 ID3_TagImpl::ID3_TagImpl(const char *name)
92  : _frames(),
93  _cursor(_frames.begin()),
94  _file_name(),
95  _file_size(0),
96  _prepended_bytes(0),
97  _appended_bytes(0),
98  _is_file_writable(false),
99  _mp3_info(NULL) // need to do this before this->Clear()
100 {
101  this->Clear();
102  if (name)
103  {
104  this->Link(name);
105  }
106 }
107 
109  : _frames(),
110  _cursor(_frames.begin()),
111  _file_name(),
112  _file_size(0),
113  _prepended_bytes(0),
114  _appended_bytes(0),
115  _is_file_writable(false),
116  _mp3_info(NULL) // need to do this before this->Clear()
117 {
118  *this = tag;
119 }
120 
122 {
123  this->Clear();
124 }
125 
127 {
128  for (iterator cur = _frames.begin(); cur != _frames.end(); ++cur)
129  {
130  if (*cur)
131  {
132  delete *cur;
133  *cur = NULL;
134  }
135  }
136  _frames.clear();
137  _cursor = _frames.begin();
138  _is_padded = true;
139 
140  _hdr.Clear();
141  _hdr.SetSpec(ID3V2_LATEST);
142 
143  _tags_to_parse.clear();
144  if (_mp3_info)
145  delete _mp3_info; // Also deletes _mp3_header
146 
147  _mp3_info = NULL;
148 
149  _changed = true;
150 }
151 
152 
154 {
155  this->AddFrame(&frame);
156 }
157 
159 {
160  if (frame)
161  {
162  ID3_Frame* frm = new ID3_Frame(*frame);
163  this->AttachFrame(frm);
164  }
165 }
166 
168 {
169 
170  if (NULL == frame)
171  {
172  // log this
173  return false;
174  //ID3_THROW(ID3E_NoData);
175  }
176 
177  _frames.push_back(frame);
178  _cursor = _frames.begin();
179 
180  _changed = true;
181  return true;
182 }
183 
184 
186 {
187  ID3_Frame *frm = NULL;
188 
189  iterator fi = Find(frame);
190  if (fi != _frames.end())
191  {
192  frm = *fi;
193  _frames.erase(fi);
194  _cursor = _frames.begin();
195  _changed = true;
196  }
197 
198  return frm;
199 }
200 
201 
203 {
204  bool changed = _changed;
205 
206  if (! changed)
207  {
208  for (const_iterator fi = _frames.begin(); fi != _frames.end(); ++fi)
209  {
210  if (*fi)
211  {
212  changed = (*fi)->HasChanged();
213  }
214 
215  if (changed)
216  {
217  break;
218  }
219  }
220  }
221 
222  return changed;
223 }
224 
226 {
227  bool changed = _hdr.SetSpec(spec);
228  _changed = _changed || changed;
229  return changed;
230 }
231 
233 {
234  return _hdr.GetSpec();
235 }
236 
238 {
239  bool changed = _hdr.SetUnsync(b);
240  _changed = changed || _changed;
241  return changed;
242 }
243 
245 {
246  bool changed = _hdr.SetExtended(ext);
247  _changed = changed || _changed;
248  return changed;
249 }
250 
252 {
253  bool changed = _hdr.SetExperimental(exp);
254  _changed = changed || _changed;
255  return changed;
256 }
257 
259 {
260  return _hdr.GetUnsync();
261 }
262 
264 {
265  return _hdr.GetExtended();
266 }
267 
269 {
270  return _hdr.GetExperimental();
271 }
272 
274 {
275  return _hdr.GetFooter();
276 }
277 
279 {
280  if (this->GetExtended())
281  if (this->GetSpec() == ID3V2_4_0)
282  return 6; //minimal ID3v2.4 ext header size
283  else if (this->GetSpec() == ID3V2_3_0)
284  return 10; //minimal ID3v2.3 ext header size
285  else
286  return 0; //not implemented
287  else
288  return 0;;
289 }
290 
292 {
293  bool changed = (_is_padded != pad);
294  _changed = changed || _changed;
295  if (changed)
296  {
297  _is_padded = pad;
298  }
299 
300  return changed;
301 }
302 
303 
304 ID3_TagImpl &
306 {
307  this->Clear();
308 
309  this->SetUnsync(rTag.GetUnsync());
310  this->SetExtended(rTag.GetExtendedHeader());
311  this->SetExperimental(rTag.GetExperimental());
312 
313  ID3_Tag::ConstIterator* iter = rTag.CreateIterator();
314  const ID3_Frame* frame = NULL;
315  while (NULL != (frame = iter->GetNext()))
316  {
317  this->AttachFrame(new ID3_Frame(*frame));
318  }
319  delete iter;
320  return *this;
321 }
322 
323 size_t ID3_GetDataSize(const ID3_TagImpl& tag)
324 {
325  return tag.GetFileSize() - tag.GetPrependedBytes() - tag.GetAppendedBytes();
326 }
327 
bool clear()
Definition: flags.h:46
The representative class of an id3v2 frame.
virtual bool Clear()
Definition: header.h:73
ID3_V2Spec GetSpec() const
Definition: header.h:62
virtual int_type readChar()
Read a single character and advance the internal position.
Definition: reader.h:65
virtual const ID3_Frame * GetNext()=0
bool SetExperimental(bool b)
Definition: header_tag.h:80
bool GetUnsync() const
Definition: header_tag.h:72
static const char *const ID
Definition: header_tag.h:100
bool GetExtended() const
Definition: header_tag.h:79
bool GetExperimental() const
Definition: header_tag.h:86
bool SetSpec(ID3_V2Spec)
Definition: header_tag.cpp:39
bool SetExtended(bool b)
Definition: header_tag.h:73
bool SetUnsync(bool b)
Definition: header_tag.h:66
bool GetFooter() const
Definition: header_tag.h:93
The representative class of an id3 tag.
Definition: tag.h:42
bool GetUnsync() const
Definition: tag.cpp:463
bool GetExperimental() const
Definition: tag.cpp:473
bool GetExtendedHeader() const
Definition: tag.cpp:468
Iterator * CreateIterator()
Definition: tag.cpp:1115
size_t GetFileSize() const
Definition: tag_impl.h:113
size_t GetAppendedBytes() const
Definition: tag_impl.h:112
bool SetSpec(ID3_V2Spec)
Definition: tag_impl.cpp:225
bool SetExperimental(bool)
Definition: tag_impl.cpp:251
ID3_Frame * Find(ID3_FrameID id) const
Definition: tag_find.cpp:61
size_t GetExtendedBytes() const
Definition: tag_impl.cpp:278
ID3_TagImpl(const char *name=NULL)
Definition: tag_impl.cpp:91
void AddFrame(const ID3_Frame &)
Definition: tag_impl.cpp:153
bool GetExperimental() const
Definition: tag_impl.cpp:268
bool GetUnsync() const
Definition: tag_impl.cpp:258
Frames::iterator iterator
Definition: tag_impl.h:77
size_t GetPrependedBytes() const
Definition: tag_impl.h:111
bool SetExtended(bool)
Definition: tag_impl.cpp:244
bool SetPadding(bool)
Definition: tag_impl.cpp:291
size_t Link(const char *fileInfo, flags_t=(flags_t) ID3TT_ALL)
Definition: tag_file.cpp:131
virtual ~ID3_TagImpl()
Definition: tag_impl.cpp:121
bool GetExtended() const
Definition: tag_impl.cpp:263
ID3_TagImpl & operator=(const ID3_Tag &)
Definition: tag_impl.cpp:305
Frames::const_iterator const_iterator
Definition: tag_impl.h:78
ID3_Frame * RemoveFrame(const ID3_Frame *)
Definition: tag_impl.cpp:185
bool SetUnsync(bool)
Definition: tag_impl.cpp:237
bool GetFooter() const
Definition: tag_impl.cpp:273
ID3_V2Spec GetSpec() const
Definition: tag_impl.cpp:232
static size_t IsV2Tag(ID3_Reader &)
Definition: tag_impl.cpp:38
bool AttachFrame(ID3_Frame *)
Definition: tag_impl.cpp:167
bool HasChanged() const
Definition: tag_impl.cpp:202
void Clear()
Definition: tag_impl.cpp:126
#define NULL
Definition: globals.h:743
ID3_V2Spec
Definition: globals.h:162
@ ID3V2_LATEST
Definition: globals.h:169
@ ID3V2_4_0
Definition: globals.h:167
@ ID3V2_3_0
Definition: globals.h:166
unsigned char uchar
Definition: globals.h:114
Definition: tag_impl.h:42
size_t ID3_GetDataSize(const ID3_TagImpl &tag)
Definition: tag_impl.cpp:323