id3lib  3.8.3
field_string_ascii.cpp
Go to the documentation of this file.
1 // $Id: field_string_ascii.cpp,v 1.29 2003/03/02 14:23:58 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 #include "field_impl.h"
28 #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h"
29 #include "io_helpers.h"
30 
31 using namespace dami;
32 
45 size_t ID3_FieldImpl::Set(const char* data)
46 {
47  size_t len = 0;
48  if ((this->GetType() == ID3FTY_TEXTSTRING) && data)
49  {
50  String str(data);
51  len = this->SetText_i(str);
52  }
53  return len;
54 }
55 
56 // the ::Get() function for ASCII
57 
87 size_t ID3_FieldImpl::Get(char* buffer, size_t maxLength) const
88 {
89  size_t size = 0;
90  if (this->GetType() == ID3FTY_TEXTSTRING &&
91  this->GetEncoding() == ID3TE_ASCII &&
92  buffer != NULL && maxLength > 0)
93  {
94  String data = this->GetText();
95  size = dami::min(maxLength, data.size());
96  ::memcpy(buffer, data.data(), size);
97  if (size < maxLength)
98  {
99  buffer[size] = '\0';
100  }
101  }
102 
103  return size;
104 }
105 
106 size_t ID3_FieldImpl::Get(char* buf, size_t maxLen, size_t index) const
107 {
108  size_t size = 0;
109  if (this->GetType() == ID3FTY_TEXTSTRING &&
110  this->GetEncoding() == ID3TE_ASCII &&
111  buf != NULL && maxLen > 0)
112  {
113  String data = this->GetTextItem(index);
114  size = dami::min(maxLen, data.size());
115  ::memcpy(buf, data.data(), size);
116  if (size < maxLen)
117  {
118  buf[size] = '\0';
119  }
120  }
121  return size;
122 }
123 
125 {
126  String data;
127  if (this->GetType() == ID3FTY_TEXTSTRING)
128  {
129  data = _text;
130  }
131  return data;
132 }
133 
134 String ID3_FieldImpl::GetTextItem(size_t index) const
135 {
136  String data;
137  if (this->GetType() == ID3FTY_TEXTSTRING &&
138  this->GetEncoding() == ID3TE_ASCII)
139  {
140  const char* raw = this->GetRawTextItem(index);
141  if (raw != NULL)
142  {
143  data = raw;
144  }
145  }
146  return data;
147 }
148 
149 namespace
150 {
151  String getFixed(String data, size_t size)
152  {
153  String text(data, 0, size);
154  if (text.size() < size)
155  {
156  text.append(size - text.size(), '\0');
157  }
158  return text;
159  }
160 }
161 
162 
163 size_t ID3_FieldImpl::SetText_i(String data)
164 {
165  this->Clear();
166  if (_fixed_size > 0)
167  {
168  _text = getFixed(data, _fixed_size);
169  }
170  else
171  {
172  _text = data;
173  }
174  ID3D_NOTICE( "SetText_i: text = \"" << _text << "\"" );
175  _changed = true;
176 
177  if (_text.size() == 0)
178  {
179  _num_items = 0;
180  }
181  else
182  {
183  _num_items = 1;
184  }
185 
186  return _text.size();
187 }
188 
189 size_t ID3_FieldImpl::SetText(String data)
190 {
191  size_t len = 0;
192  if (this->GetType() == ID3FTY_TEXTSTRING)
193  {
194  len = this->SetText_i(data);
195  }
196  return len;
197 }
198 
199 
213 size_t ID3_FieldImpl::AddText_i(String data)
214 {
215  size_t len = 0; // how much of str we copied into this field (max is strLen)
216  ID3D_NOTICE ("ID3_FieldImpl::AddText_i: Adding \"" << data << "\"" );
217  if (this->GetNumTextItems() == 0)
218  {
219  // there aren't any text items in the field so just assign the string to
220  // the field
221  len = this->SetText_i(data);
222  }
223  else
224  {
225 
226  // ASSERT(_fixed_size == 0)
227  _text += '\0';
228  if (this->GetEncoding() == ID3TE_UNICODE)
229  {
230  _text += '\0';
231  }
232  _text.append(data);
233  len = data.size();
234  _num_items++;
235  }
236 
237  return len;
238 }
239 
240 size_t ID3_FieldImpl::AddText(String data)
241 {
242  size_t len = 0;
243  if (this->GetType() == ID3FTY_TEXTSTRING)
244  {
245  len = this->AddText_i(data);
246  }
247  return len;
248 }
249 
250 size_t ID3_FieldImpl::Add(const char* data)
251 {
252  size_t len = 0;
253  if (this->GetType() == ID3FTY_TEXTSTRING)
254  {
255  String str(data);
256  len = this->AddText_i(str);
257  }
258  return len;
259 }
260 
261 const char* ID3_FieldImpl::GetRawText() const
262 {
263  const char* text = NULL;
264  if (this->GetType() == ID3FTY_TEXTSTRING &&
265  this->GetEncoding() == ID3TE_ASCII)
266  {
267  text = _text.c_str();
268  }
269  return text;
270 }
271 
272 const char* ID3_FieldImpl::GetRawTextItem(size_t index) const
273 {
274  const char* text = NULL;
275  if (this->GetType() == ID3FTY_TEXTSTRING &&
276  this->GetEncoding() == ID3TE_ASCII &&
277  index < this->GetNumTextItems())
278  {
279  text = _text.c_str();
280  for (size_t i = 0; i < index; ++i)
281  {
282  text += strlen(text) + 1;
283  }
284  }
285  return text;
286 }
287 
288 namespace
289 {
290  String readEncodedText(ID3_Reader& reader, size_t len, ID3_TextEnc enc)
291  {
292  if (enc == ID3TE_ASCII)
293  {
294  return io::readText(reader, len);
295  }
296  return io::readUnicodeText(reader, len);
297  }
298 
299  String readEncodedString(ID3_Reader& reader, ID3_TextEnc enc)
300  {
301  if (enc == ID3TE_ASCII)
302  {
303  return io::readString(reader);
304  }
305  return io::readUnicodeString(reader);
306  }
307 
308  size_t writeEncodedText(ID3_Writer& writer, String data, ID3_TextEnc enc)
309  {
310  if (enc == ID3TE_ASCII)
311  {
312  return io::writeText(writer, data);
313  }
314  return io::writeUnicodeText(writer, data);
315  }
316 
317  size_t writeEncodedString(ID3_Writer& writer, String data, ID3_TextEnc enc)
318  {
319  if (enc == ID3TE_ASCII)
320  {
321  return io::writeString(writer, data);
322  }
323  return io::writeUnicodeString(writer, data);
324  }
325 }
326 
328 {
329  ID3D_NOTICE( "ID3_Field::ParseText(): reader.getBeg() = " << reader.getBeg() );
330  ID3D_NOTICE( "ID3_Field::ParseText(): reader.getCur() = " << reader.getCur() );
331  ID3D_NOTICE( "ID3_Field::ParseText(): reader.getEnd() = " << reader.getEnd() );
332  this->Clear();
333 
334  ID3_TextEnc enc = this->GetEncoding();
335  size_t fixed_size = this->Size();
336  if (fixed_size)
337  {
338  ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string" );
339  // The string is of fixed length
340  String text = readEncodedText(reader, fixed_size, enc);
341  this->SetText(text);
342  ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string = " << text );
343  }
344  else if (_flags & ID3FF_LIST)
345  {
346  ID3D_NOTICE( "ID3_Field::ParseText(): text list" );
347  // lists are always the last field in a frame. parse all remaining
348  // characters in the reader
349  while (!reader.atEnd())
350  {
351  String text = readEncodedString(reader, enc);
352  this->AddText(text);
353  ID3D_NOTICE( "ID3_Field::ParseText(): adding string = " << text );
354  }
355  }
356  else if (_flags & ID3FF_CSTR)
357  {
358  ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string" );
359  String text = readEncodedString(reader, enc);
360  this->SetText(text);
361  ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string = " << text );
362  }
363  else
364  {
365  ID3D_NOTICE( "ID3_Field::ParseText(): last field string" );
366  String text = readEncodedText(reader, reader.remainingBytes(), enc);
367  // not null terminated.
368  this->AddText(text);
369  ID3D_NOTICE( "ID3_Field::ParseText(): last field string = " << text );
370  }
371 
372  _changed = false;
373  return true;
374 }
375 
377 {
378  ID3_TextEnc enc = this->GetEncoding();
379 
380  if (_flags & ID3FF_CSTR)
381  {
382  writeEncodedString(writer, _text, enc);
383  }
384  else
385  {
386  writeEncodedText(writer, _text, enc);
387  }
388  _changed = false;
389 };
390 
400 {
401  return _num_items;
402 }
403 
dami::String GetText() const
size_t Add(const char *data)
const char * GetRawTextItem(size_t) const
size_t SetText(dami::String)
void RenderText(ID3_Writer &) const
const char * GetRawText() const
size_t GetNumTextItems() const
Returns the number of items in a text list.
dami::String GetTextItem(size_t) const
size_t AddText(dami::String)
void Set(uint32)
Sets the value of the field to the specified integer.
uint32 Get() const
Returns the value of the integer field.
bool ParseText(ID3_Reader &)
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
virtual size_type remainingBytes()
Definition: reader.h:109
virtual pos_type getBeg()
Return the beginning position in the reader.
Definition: reader.h:48
#define NULL
Definition: globals.h:743
ID3_TextEnc
Enumeration of the types of text encodings: ascii or unicode.
Definition: globals.h:138
@ ID3TE_ASCII
Definition: globals.h:145
@ ID3TE_UNICODE
Definition: globals.h:146
@ ID3FF_CSTR
Definition: globals.h:344
@ ID3FF_LIST
Definition: globals.h:345
@ ID3FTY_TEXTSTRING
Definition: globals.h:356
Definition: tag_impl.h:42
const T & min(const T &a, const T &b)
Definition: utils.h:51