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
31using namespace dami;
32
38
45size_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
87size_t ID3_FieldImpl::Get(char* buffer, size_t maxLength) const
88{
89 size_t size = 0;
90 if (this->GetType() == ID3FTY_TEXTSTRING &&
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
106size_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 &&
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
134String ID3_FieldImpl::GetTextItem(size_t index) const
135{
136 String data;
137 if (this->GetType() == ID3FTY_TEXTSTRING &&
139 {
140 const char* raw = this->GetRawTextItem(index);
141 if (raw != NULL)
142 {
143 data = raw;
144 }
145 }
146 return data;
147}
148
149namespace
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
163size_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
189size_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
213size_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';
229 {
230 _text += '\0';
231 }
232 _text.append(data);
233 len = data.size();
234 _num_items++;
235 }
236
237 return len;
238}
239
240size_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
250size_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
261const char* ID3_FieldImpl::GetRawText() const
262{
263 const char* text = NULL;
264 if (this->GetType() == ID3FTY_TEXTSTRING &&
266 {
267 text = _text.c_str();
268 }
269 return text;
270}
271
272const char* ID3_FieldImpl::GetRawTextItem(size_t index) const
273{
274 const char* text = NULL;
275 if (this->GetType() == ID3FTY_TEXTSTRING &&
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
288namespace
289{
290 // UTF-16BE is stored big-endian without a BOM; id3lib keeps unicode text in
291 // host byte order internally, so swap the byte pairs after reading.
292 void swapPairs(String& s)
293 {
294 for (size_t i = 0; i + 1 < s.size(); i += 2)
295 {
296 char t = s[i]; s[i] = s[i+1]; s[i+1] = t;
297 }
298 }
299
300 String readEncodedText(ID3_Reader& reader, size_t len, ID3_TextEnc enc)
301 {
303 {
304 return io::readText(reader, len);
305 }
306 String text = io::readUnicodeText(reader, len);
307 if (enc == ID3TE_UTF16BE)
308 {
309 swapPairs(text);
310 }
311 return text;
312 }
313
314 String readEncodedString(ID3_Reader& reader, ID3_TextEnc enc)
315 {
317 {
318 return io::readString(reader);
319 }
320 String text = io::readUnicodeString(reader);
321 if (enc == ID3TE_UTF16BE)
322 {
323 swapPairs(text);
324 }
325 return text;
326 }
327
328 size_t writeEncodedText(ID3_Writer& writer, String data, ID3_TextEnc enc)
329 {
331 {
332 return io::writeText(writer, data);
333 }
334 // UTF-16 carries a BOM, UTF-16BE does not.
335 return io::writeUnicodeText(writer, data, enc != ID3TE_UTF16BE);
336 }
337
338 size_t writeEncodedString(ID3_Writer& writer, String data, ID3_TextEnc enc)
339 {
341 {
342 return io::writeString(writer, data);
343 }
344 // UTF-16 carries a BOM, UTF-16BE does not.
345 return io::writeUnicodeString(writer, data, enc != ID3TE_UTF16BE);
346 }
347}
348
350{
351 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getBeg() = " << reader.getBeg() );
352 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getCur() = " << reader.getCur() );
353 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getEnd() = " << reader.getEnd() );
354 this->Clear();
355
356 ID3_TextEnc enc = this->GetEncoding();
357 size_t fixed_size = this->Size();
358 if (fixed_size)
359 {
360 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string" );
361 // The string is of fixed length
362 String text = readEncodedText(reader, fixed_size, enc);
363 this->SetText(text);
364 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string = " << text );
365 }
366 else if (_flags & ID3FF_LIST)
367 {
368 ID3D_NOTICE( "ID3_Field::ParseText(): text list" );
369 // lists are always the last field in a frame. parse all remaining
370 // characters in the reader
371 while (!reader.atEnd())
372 {
373 String text = readEncodedString(reader, enc);
374 this->AddText(text);
375 ID3D_NOTICE( "ID3_Field::ParseText(): adding string = " << text );
376 }
377 }
378 else if (_flags & ID3FF_CSTR)
379 {
380 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string" );
381 String text = readEncodedString(reader, enc);
382 this->SetText(text);
383 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string = " << text );
384 }
385 else
386 {
387 ID3D_NOTICE( "ID3_Field::ParseText(): last field string" );
388 String text = readEncodedText(reader, reader.remainingBytes(), enc);
389 // not null terminated.
390 this->AddText(text);
391 ID3D_NOTICE( "ID3_Field::ParseText(): last field string = " << text );
392 }
393
394 _changed = false;
395 return true;
396}
397
399{
400 ID3_TextEnc enc = this->GetEncoding();
401
402 if (_flags & ID3FF_CSTR)
403 {
404 writeEncodedString(writer, _text, enc);
405 }
406 else
407 {
408 writeEncodedText(writer, _text, enc);
409 }
410 _changed = false;
411};
412
422{
423 return _num_items;
424}
425
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)
ID3_FieldType GetType() const
Definition field_impl.h:103
void Set(uint32)
Sets the value of the field to the specified integer.
void Clear()
Clears any data and frees any memory associated with the field.
Definition field.cpp:923
ID3_TextEnc GetEncoding() const
Definition field_impl.h:105
uint32 Get() const
Returns the value of the integer field.
bool ParseText(ID3_Reader &)
size_t Size() const
Returns the size of a field.
Definition field.cpp:1018
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
#define ID3TE_IS_SINGLE_BYTE_ENC(enc)
Definition globals.h:149
ID3_TextEnc
Enumeration of the types of text encodings: ascii or unicode.
Definition globals.h:138
@ ID3TE_UTF16BE
Definition globals.h:142
@ ID3FF_CSTR
Definition globals.h:344
@ ID3FF_LIST
Definition globals.h:345
#define ID3TE_IS_DOUBLE_BYTE_ENC(enc)
Definition globals.h:150
@ ID3FTY_TEXTSTRING
Definition globals.h:356