00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if defined HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031
00032
00033 #include <string.h>
00034 #include <stdlib.h>
00035
00036 #include "field_impl.h"
00037 #include "utils.h"
00038 #include "io_helpers.h"
00039
00040 using namespace dami;
00041
00054 size_t ID3_FieldImpl::Set(const char* data)
00055 {
00056 size_t len = 0;
00057 if (this->GetType() == ID3FTY_TEXTSTRING)
00058 {
00059 String str(data);
00060 len = this->SetText_i(str);
00061 }
00062 return len;
00063 }
00064
00065
00066
00096 size_t ID3_FieldImpl::Get(char* buffer, size_t maxLength) const
00097 {
00098 size_t size = 0;
00099 if (this->GetType() == ID3FTY_TEXTSTRING &&
00100 this->GetEncoding() == ID3TE_ASCII &&
00101 buffer != NULL && maxLength > 0)
00102 {
00103 String data = this->GetText();
00104 size = dami::min(maxLength, data.size());
00105 ::memcpy(buffer, data.data(), size);
00106 if (size < maxLength)
00107 {
00108 buffer[size] = '\0';
00109 }
00110 }
00111
00112 return size;
00113 }
00114
00115 size_t ID3_FieldImpl::Get(char* buf, size_t maxLen, index_t index) const
00116 {
00117 size_t size = 0;
00118 if (this->GetType() == ID3FTY_TEXTSTRING &&
00119 this->GetEncoding() == ID3TE_ASCII &&
00120 buf != NULL && maxLen > 0)
00121 {
00122 String data = this->GetTextItem(index);
00123 size = dami::min(maxLen, data.size());
00124 ::memcpy(buf, data.data(), size);
00125 if (size < maxLen)
00126 {
00127 buf[size] = '\0';
00128 }
00129 }
00130 return size;
00131 }
00132
00133 String ID3_FieldImpl::GetText() const
00134 {
00135 String data;
00136 if (this->GetType() == ID3FTY_TEXTSTRING)
00137 {
00138 data = _text;
00139 }
00140 return data;
00141 }
00142
00143 String ID3_FieldImpl::GetTextItem(index_t index) const
00144 {
00145 String data;
00146 if (this->GetType() == ID3FTY_TEXTSTRING &&
00147 this->GetEncoding() == ID3TE_ASCII)
00148 {
00149 const char* raw = this->GetRawTextItem(index);
00150 if (raw != NULL)
00151 {
00152 data = raw;
00153 }
00154 }
00155 return data;
00156 }
00157
00158 namespace
00159 {
00160 String getFixed(String data, size_t size)
00161 {
00162 String text(data, 0, size);
00163 if (text.size() < size)
00164 {
00165 text.append(size - text.size(), '\0');
00166 }
00167 return text;
00168 }
00169 }
00170
00171
00172 size_t ID3_FieldImpl::SetText_i(String data)
00173 {
00174 this->Clear();
00175 if (_fixed_size > 0)
00176 {
00177 _text = getFixed(data, _fixed_size);
00178 }
00179 else
00180 {
00181 _text = data;
00182 }
00183 ID3D_NOTICE( "SetText_i: text = \"" << _text << "\"" );
00184 _changed = true;
00185
00186 if (_text.size() == 0)
00187 {
00188 _num_items = 0;
00189 }
00190 else
00191 {
00192 _num_items = 1;
00193 }
00194
00195 return _text.size();
00196 }
00197
00198 size_t ID3_FieldImpl::SetText(String data)
00199 {
00200 size_t len = 0;
00201 if (this->GetType() == ID3FTY_TEXTSTRING)
00202 {
00203 len = this->SetText_i(data);
00204 }
00205 return len;
00206 }
00207
00208
00222 size_t ID3_FieldImpl::AddText_i(String data)
00223 {
00224 size_t len = 0;
00225 ID3D_NOTICE ("ID3_FieldImpl::AddText_i: Adding \"" << data << "\"" );
00226 if (this->GetNumTextItems() == 0)
00227 {
00228
00229
00230 len = this->SetText_i(data);
00231 }
00232 else
00233 {
00234
00235
00236 _text += '\0';
00237 if (this->GetEncoding() == ID3TE_UNICODE)
00238 {
00239 _text += '\0';
00240 }
00241 _text.append(data);
00242 len = data.size();
00243 _num_items++;
00244 }
00245
00246 return len;
00247 }
00248
00249 size_t ID3_FieldImpl::AddText(String data)
00250 {
00251 size_t len = 0;
00252 if (this->GetType() == ID3FTY_TEXTSTRING)
00253 {
00254 len = this->AddText_i(data);
00255 }
00256 return len;
00257 }
00258
00259 size_t ID3_FieldImpl::Add(const char* data)
00260 {
00261 size_t len = 0;
00262 if (this->GetType() == ID3FTY_TEXTSTRING)
00263 {
00264 String str(data);
00265 len = this->AddText_i(str);
00266 }
00267 return len;
00268 }
00269
00270 const char* ID3_FieldImpl::GetRawText() const
00271 {
00272 const char* text = NULL;
00273 if (this->GetType() == ID3FTY_TEXTSTRING &&
00274 this->GetEncoding() == ID3TE_ASCII)
00275 {
00276 text = _text.c_str();
00277 }
00278 return text;
00279 }
00280
00281 const char* ID3_FieldImpl::GetRawTextItem(index_t index) const
00282 {
00283 const char* text = NULL;
00284 if (this->GetType() == ID3FTY_TEXTSTRING &&
00285 this->GetEncoding() == ID3TE_ASCII &&
00286 index < this->GetNumTextItems())
00287 {
00288 text = _text.c_str();
00289 for (size_t i = 0; i < index; ++i)
00290 {
00291 text += strlen(text) + 1;
00292 }
00293 }
00294 return text;
00295 }
00296
00297 namespace
00298 {
00299 String readEncodedText(ID3_Reader& reader, size_t len, ID3_TextEnc enc)
00300 {
00301 if (enc == ID3TE_ASCII)
00302 {
00303 return io::readText(reader, len);
00304 }
00305 return io::readUnicodeText(reader, len);
00306 }
00307
00308 String readEncodedString(ID3_Reader& reader, ID3_TextEnc enc)
00309 {
00310 if (enc == ID3TE_ASCII)
00311 {
00312 return io::readString(reader);
00313 }
00314 return io::readUnicodeString(reader);
00315 }
00316
00317 size_t writeEncodedText(ID3_Writer& writer, String data, ID3_TextEnc enc)
00318 {
00319 if (enc == ID3TE_ASCII)
00320 {
00321 return io::writeText(writer, data);
00322 }
00323 return io::writeUnicodeText(writer, data);
00324 }
00325
00326 size_t writeEncodedString(ID3_Writer& writer, String data, ID3_TextEnc enc)
00327 {
00328 if (enc == ID3TE_ASCII)
00329 {
00330 return io::writeString(writer, data);
00331 }
00332 return io::writeUnicodeString(writer, data);
00333 }
00334 }
00335
00336 bool ID3_FieldImpl::ParseText(ID3_Reader& reader)
00337 {
00338 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getBeg() = " << reader.getBeg() );
00339 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getCur() = " << reader.getCur() );
00340 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getEnd() = " << reader.getEnd() );
00341 this->Clear();
00342
00343 ID3_TextEnc enc = this->GetEncoding();
00344 size_t fixed_size = this->Size();
00345 if (fixed_size)
00346 {
00347 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string" );
00348
00349 String text = readEncodedText(reader, fixed_size, enc);
00350 this->SetText(text);
00351 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string = " << text );
00352 }
00353 else if (_flags & ID3FF_LIST)
00354 {
00355 ID3D_NOTICE( "ID3_Field::ParseText(): text list" );
00356
00357
00358 while (!reader.atEnd())
00359 {
00360 String text = readEncodedString(reader, enc);
00361 this->AddText(text);
00362 ID3D_NOTICE( "ID3_Field::ParseText(): adding string = " << text );
00363 }
00364 }
00365 else if (_flags & ID3FF_CSTR)
00366 {
00367 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string" );
00368 String text = readEncodedString(reader, enc);
00369 this->SetText(text);
00370 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string = " << text );
00371 }
00372 else
00373 {
00374 ID3D_NOTICE( "ID3_Field::ParseText(): last field string" );
00375 String text = readEncodedText(reader, reader.remainingBytes(), enc);
00376
00377 this->AddText(text);
00378 ID3D_NOTICE( "ID3_Field::ParseText(): last field string = " << text );
00379 }
00380
00381 _changed = false;
00382 return true;
00383 }
00384
00385 void ID3_FieldImpl::RenderText(ID3_Writer& writer) const
00386 {
00387 ID3_TextEnc enc = this->GetEncoding();
00388
00389 if (_flags & ID3FF_CSTR)
00390 {
00391 writeEncodedString(writer, _text, enc);
00392 }
00393 else
00394 {
00395 writeEncodedText(writer, _text, enc);
00396 }
00397 _changed = false;
00398 };
00399
00408 size_t ID3_FieldImpl::GetNumTextItems() const
00409 {
00410 return _num_items;
00411 }
00412