id3lib 3.8.3
|
00001 // $Id: field_string_ascii.cpp,v 1.29 2003/03/02 14:23:58 t1mpy Exp $ 00002 00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags 00004 // Copyright 1999, 2000 Scott Thomas Haug 00005 00006 // This library is free software; you can redistribute it and/or modify it 00007 // under the terms of the GNU Library General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or (at your 00009 // option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, but WITHOUT 00012 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 // License for more details. 00015 // 00016 // You should have received a copy of the GNU Library General Public License 00017 // along with this library; if not, write to the Free Software Foundation, 00018 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 00020 // The id3lib authors encourage improvements and optimisations to be sent to 00021 // the id3lib coordinator. Please see the README file for details on where to 00022 // send such submissions. See the AUTHORS file for a list of people who have 00023 // contributed to id3lib. See the ChangeLog file for a list of changes to 00024 // id3lib. These files are distributed with id3lib at 00025 // http://download.sourceforge.net/id3lib/ 00026 00027 #include "field_impl.h" 00028 #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h" 00029 #include "io_helpers.h" 00030 00031 using namespace dami; 00032 00045 size_t ID3_FieldImpl::Set(const char* data) 00046 { 00047 size_t len = 0; 00048 if ((this->GetType() == ID3FTY_TEXTSTRING) && data) 00049 { 00050 String str(data); 00051 len = this->SetText_i(str); 00052 } 00053 return len; 00054 } 00055 00056 // the ::Get() function for ASCII 00057 00087 size_t ID3_FieldImpl::Get(char* buffer, size_t maxLength) const 00088 { 00089 size_t size = 0; 00090 if (this->GetType() == ID3FTY_TEXTSTRING && 00091 this->GetEncoding() == ID3TE_ASCII && 00092 buffer != NULL && maxLength > 0) 00093 { 00094 String data = this->GetText(); 00095 size = dami::min(maxLength, data.size()); 00096 ::memcpy(buffer, data.data(), size); 00097 if (size < maxLength) 00098 { 00099 buffer[size] = '\0'; 00100 } 00101 } 00102 00103 return size; 00104 } 00105 00106 size_t ID3_FieldImpl::Get(char* buf, size_t maxLen, size_t index) const 00107 { 00108 size_t size = 0; 00109 if (this->GetType() == ID3FTY_TEXTSTRING && 00110 this->GetEncoding() == ID3TE_ASCII && 00111 buf != NULL && maxLen > 0) 00112 { 00113 String data = this->GetTextItem(index); 00114 size = dami::min(maxLen, data.size()); 00115 ::memcpy(buf, data.data(), size); 00116 if (size < maxLen) 00117 { 00118 buf[size] = '\0'; 00119 } 00120 } 00121 return size; 00122 } 00123 00124 String ID3_FieldImpl::GetText() const 00125 { 00126 String data; 00127 if (this->GetType() == ID3FTY_TEXTSTRING) 00128 { 00129 data = _text; 00130 } 00131 return data; 00132 } 00133 00134 String ID3_FieldImpl::GetTextItem(size_t index) const 00135 { 00136 String data; 00137 if (this->GetType() == ID3FTY_TEXTSTRING && 00138 this->GetEncoding() == ID3TE_ASCII) 00139 { 00140 const char* raw = this->GetRawTextItem(index); 00141 if (raw != NULL) 00142 { 00143 data = raw; 00144 } 00145 } 00146 return data; 00147 } 00148 00149 namespace 00150 { 00151 String getFixed(String data, size_t size) 00152 { 00153 String text(data, 0, size); 00154 if (text.size() < size) 00155 { 00156 text.append(size - text.size(), '\0'); 00157 } 00158 return text; 00159 } 00160 } 00161 00162 00163 size_t ID3_FieldImpl::SetText_i(String data) 00164 { 00165 this->Clear(); 00166 if (_fixed_size > 0) 00167 { 00168 _text = getFixed(data, _fixed_size); 00169 } 00170 else 00171 { 00172 _text = data; 00173 } 00174 ID3D_NOTICE( "SetText_i: text = \"" << _text << "\"" ); 00175 _changed = true; 00176 00177 if (_text.size() == 0) 00178 { 00179 _num_items = 0; 00180 } 00181 else 00182 { 00183 _num_items = 1; 00184 } 00185 00186 return _text.size(); 00187 } 00188 00189 size_t ID3_FieldImpl::SetText(String data) 00190 { 00191 size_t len = 0; 00192 if (this->GetType() == ID3FTY_TEXTSTRING) 00193 { 00194 len = this->SetText_i(data); 00195 } 00196 return len; 00197 } 00198 00199 00213 size_t ID3_FieldImpl::AddText_i(String data) 00214 { 00215 size_t len = 0; // how much of str we copied into this field (max is strLen) 00216 ID3D_NOTICE ("ID3_FieldImpl::AddText_i: Adding \"" << data << "\"" ); 00217 if (this->GetNumTextItems() == 0) 00218 { 00219 // there aren't any text items in the field so just assign the string to 00220 // the field 00221 len = this->SetText_i(data); 00222 } 00223 else 00224 { 00225 00226 // ASSERT(_fixed_size == 0) 00227 _text += '\0'; 00228 if (this->GetEncoding() == ID3TE_UNICODE) 00229 { 00230 _text += '\0'; 00231 } 00232 _text.append(data); 00233 len = data.size(); 00234 _num_items++; 00235 } 00236 00237 return len; 00238 } 00239 00240 size_t ID3_FieldImpl::AddText(String data) 00241 { 00242 size_t len = 0; 00243 if (this->GetType() == ID3FTY_TEXTSTRING) 00244 { 00245 len = this->AddText_i(data); 00246 } 00247 return len; 00248 } 00249 00250 size_t ID3_FieldImpl::Add(const char* data) 00251 { 00252 size_t len = 0; 00253 if (this->GetType() == ID3FTY_TEXTSTRING) 00254 { 00255 String str(data); 00256 len = this->AddText_i(str); 00257 } 00258 return len; 00259 } 00260 00261 const char* ID3_FieldImpl::GetRawText() const 00262 { 00263 const char* text = NULL; 00264 if (this->GetType() == ID3FTY_TEXTSTRING && 00265 this->GetEncoding() == ID3TE_ASCII) 00266 { 00267 text = _text.c_str(); 00268 } 00269 return text; 00270 } 00271 00272 const char* ID3_FieldImpl::GetRawTextItem(size_t index) const 00273 { 00274 const char* text = NULL; 00275 if (this->GetType() == ID3FTY_TEXTSTRING && 00276 this->GetEncoding() == ID3TE_ASCII && 00277 index < this->GetNumTextItems()) 00278 { 00279 text = _text.c_str(); 00280 for (size_t i = 0; i < index; ++i) 00281 { 00282 text += strlen(text) + 1; 00283 } 00284 } 00285 return text; 00286 } 00287 00288 namespace 00289 { 00290 String readEncodedText(ID3_Reader& reader, size_t len, ID3_TextEnc enc) 00291 { 00292 if (enc == ID3TE_ASCII) 00293 { 00294 return io::readText(reader, len); 00295 } 00296 return io::readUnicodeText(reader, len); 00297 } 00298 00299 String readEncodedString(ID3_Reader& reader, ID3_TextEnc enc) 00300 { 00301 if (enc == ID3TE_ASCII) 00302 { 00303 return io::readString(reader); 00304 } 00305 return io::readUnicodeString(reader); 00306 } 00307 00308 size_t writeEncodedText(ID3_Writer& writer, String data, ID3_TextEnc enc) 00309 { 00310 if (enc == ID3TE_ASCII) 00311 { 00312 return io::writeText(writer, data); 00313 } 00314 return io::writeUnicodeText(writer, data); 00315 } 00316 00317 size_t writeEncodedString(ID3_Writer& writer, String data, ID3_TextEnc enc) 00318 { 00319 if (enc == ID3TE_ASCII) 00320 { 00321 return io::writeString(writer, data); 00322 } 00323 return io::writeUnicodeString(writer, data); 00324 } 00325 } 00326 00327 bool ID3_FieldImpl::ParseText(ID3_Reader& reader) 00328 { 00329 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getBeg() = " << reader.getBeg() ); 00330 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getCur() = " << reader.getCur() ); 00331 ID3D_NOTICE( "ID3_Field::ParseText(): reader.getEnd() = " << reader.getEnd() ); 00332 this->Clear(); 00333 00334 ID3_TextEnc enc = this->GetEncoding(); 00335 size_t fixed_size = this->Size(); 00336 if (fixed_size) 00337 { 00338 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string" ); 00339 // The string is of fixed length 00340 String text = readEncodedText(reader, fixed_size, enc); 00341 this->SetText(text); 00342 ID3D_NOTICE( "ID3_Field::ParseText(): fixed size string = " << text ); 00343 } 00344 else if (_flags & ID3FF_LIST) 00345 { 00346 ID3D_NOTICE( "ID3_Field::ParseText(): text list" ); 00347 // lists are always the last field in a frame. parse all remaining 00348 // characters in the reader 00349 while (!reader.atEnd()) 00350 { 00351 String text = readEncodedString(reader, enc); 00352 this->AddText(text); 00353 ID3D_NOTICE( "ID3_Field::ParseText(): adding string = " << text ); 00354 } 00355 } 00356 else if (_flags & ID3FF_CSTR) 00357 { 00358 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string" ); 00359 String text = readEncodedString(reader, enc); 00360 this->SetText(text); 00361 ID3D_NOTICE( "ID3_Field::ParseText(): null terminated string = " << text ); 00362 } 00363 else 00364 { 00365 ID3D_NOTICE( "ID3_Field::ParseText(): last field string" ); 00366 String text = readEncodedText(reader, reader.remainingBytes(), enc); 00367 // not null terminated. 00368 this->AddText(text); 00369 ID3D_NOTICE( "ID3_Field::ParseText(): last field string = " << text ); 00370 } 00371 00372 _changed = false; 00373 return true; 00374 } 00375 00376 void ID3_FieldImpl::RenderText(ID3_Writer& writer) const 00377 { 00378 ID3_TextEnc enc = this->GetEncoding(); 00379 00380 if (_flags & ID3FF_CSTR) 00381 { 00382 writeEncodedString(writer, _text, enc); 00383 } 00384 else 00385 { 00386 writeEncodedText(writer, _text, enc); 00387 } 00388 _changed = false; 00389 }; 00390 00399 size_t ID3_FieldImpl::GetNumTextItems() const 00400 { 00401 return _num_items; 00402 } 00403