diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 0ad56209..4c8468b7 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -4,10 +4,26 @@ include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) +include(CheckCXXCompilerFlag) include(CheckCXXSourceCompiles) include(TestBigEndian) include(TestFloatFormat) +# Determine whether your compiler supports C++0x/C++11 and enable it if possible. +# This check covers GCC, Clang and ICC. + +if(NOT MSVC AND NOT CMAKE_CXX_FLAGS MATCHES "-std=^\\s+") + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_FLAG_CXX11) + if(COMPILER_FLAG_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else() + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_FLAG_CXX0X) + if(COMPILER_FLAG_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + endif() +endif() + # Check if the size of numeric types are suitable. check_type_size("short" SIZEOF_SHORT) @@ -43,7 +59,6 @@ endif() # Determine the CPU byte order. test_big_endian(IS_BIG_ENDIAN) - if(NOT IS_BIG_ENDIAN) set(SYSTEM_BYTEORDER 1) else() @@ -61,6 +76,100 @@ else() MESSAGE(FATAL_ERROR "TagLib requires that floating point types are IEEE754 compliant.") endif() +# Determine which kind of atomic operations your compiler supports. + +check_cxx_source_compiles(" + #include + int main() { + std::atomic x; + x.fetch_add(1); + x.fetch_sub(1); + return 0; + } +" HAVE_STD_ATOMIC) + +if(NOT HAVE_STD_ATOMIC) + check_cxx_source_compiles(" + #include + int main() { + boost::atomic x(1); + x.fetch_add(1); + x.fetch_sub(1); + return 0; + } + " HAVE_BOOST_ATOMIC) + + if(NOT HAVE_BOOST_ATOMIC) + check_cxx_source_compiles(" + int main() { + volatile int x; + __sync_add_and_fetch(&x, 1); + int y = __sync_sub_and_fetch(&x, 1); + return 0; + } + " HAVE_GCC_ATOMIC) + + if(NOT HAVE_GCC_ATOMIC) + check_cxx_source_compiles(" + #include + int main() { + volatile int32_t x; + OSAtomicIncrement32Barrier(&x); + int32_t y = OSAtomicDecrement32Barrier(&x); + return 0; + } + " HAVE_MAC_ATOMIC) + + if(NOT HAVE_MAC_ATOMIC) + check_cxx_source_compiles(" + #include + int main() { + volatile LONG x; + InterlockedIncrement(&x); + LONG y = InterlockedDecrement(&x); + return 0; + } + " HAVE_WIN_ATOMIC) + + if(NOT HAVE_WIN_ATOMIC) + check_cxx_source_compiles(" + #include + int main() { + volatile int x; + __sync_add_and_fetch(&x, 1); + int y = __sync_sub_and_fetch(&x, 1); + return 0; + } + " HAVE_IA64_ATOMIC) + endif() + endif() + endif() + endif() +endif() + +# Determine which kind of smart pointers your compiler supports. + +check_cxx_source_compiles(" + #include + int main() { + std::shared_ptr x; + std::unique_ptr y; + return 0; + } +" HAVE_STD_SMART_PTR) + +if(NOT HAVE_STD_SMART_PTR) + check_cxx_source_compiles(" + #include + #include + int main() { + boost::shared_ptr x; + boost::scoped_ptr y; + return 0; + } + " HAVE_BOOST_SMART_PTR) +endif() + # Determine which kind of byte swap functions your compiler supports. # GCC's __builtin_bswap* should be checked individually @@ -134,112 +243,6 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP endif() endif() -# Determine where shared_ptr is defined regardless of C++11 support. - -check_cxx_source_compiles(" - #include - int main() { std::shared_ptr x; return 0; } -" HAVE_STD_SHARED_PTR) - -if(NOT HAVE_STD_SHARED_PTR) - check_cxx_source_compiles(" - #include - int main() { std::tr1::shared_ptr x; return 0; } - " HAVE_TR1_SHARED_PTR) - - if(NOT HAVE_TR1_SHARED_PTR) - check_cxx_source_compiles(" - #include - int main() { boost::shared_ptr x; return 0; } - " HAVE_BOOST_SHARED_PTR) - endif() -endif() - -# Determine where unique_ptr or scoped_ptr is defined regardless of C++11 support. - -check_cxx_source_compiles(" - #include - int main() { std::unique_ptr x; return 0; } -" HAVE_STD_UNIQUE_PTR) - -if(NOT HAVE_STD_UNIQUE_PTR) - check_cxx_source_compiles(" - #include - int main() { boost::scoped_ptr x; return 0; } - " HAVE_BOOST_SCOPED_PTR) -endif() - -# Determine which kind of atomic operations your compiler supports. - -check_cxx_source_compiles(" - #include - int main() { - std::atomic x; - x.fetch_add(1); - x.fetch_sub(1); - return 0; - } -" HAVE_STD_ATOMIC) - -if(NOT HAVE_STD_ATOMIC) - check_cxx_source_compiles(" - #include - int main() { - boost::atomic x(1); - x.fetch_add(1); - x.fetch_sub(1); - return 0; - } - " HAVE_BOOST_ATOMIC) - - if(NOT HAVE_BOOST_ATOMIC) - check_cxx_source_compiles(" - int main() { - volatile int x; - __sync_add_and_fetch(&x, 1); - int y = __sync_sub_and_fetch(&x, 1); - return 0; - } - " HAVE_GCC_ATOMIC) - - if(NOT HAVE_GCC_ATOMIC) - check_cxx_source_compiles(" - #include - int main() { - volatile int32_t x; - OSAtomicIncrement32Barrier(&x); - int32_t y = OSAtomicDecrement32Barrier(&x); - return 0; - } - " HAVE_MAC_ATOMIC) - - if(NOT HAVE_MAC_ATOMIC) - check_cxx_source_compiles(" - #include - int main() { - volatile LONG x; - InterlockedIncrement(&x); - LONG y = InterlockedDecrement(&x); - return 0; - } - " HAVE_WIN_ATOMIC) - - if(NOT HAVE_WIN_ATOMIC) - check_cxx_source_compiles(" - #include - int main() { - volatile int x; - __sync_add_and_fetch(&x, 1); - int y = __sync_sub_and_fetch(&x, 1); - return 0; - } - " HAVE_IA64_ATOMIC) - endif() - endif() - endif() - endif() -endif() - # Determine whether your compiler supports snprintf or sprintf_s. check_cxx_source_compiles(" @@ -287,8 +290,6 @@ endif() # Determine whether CppUnit is installed. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) - find_package(CppUnit) if(NOT CppUnit_FOUND AND BUILD_TESTS) message(STATUS "CppUnit not found, disabling tests.") diff --git a/bindings/c/tag_c.cpp b/bindings/c/tag_c.cpp index 88926088..eb32e9a2 100644 --- a/bindings/c/tag_c.cpp +++ b/bindings/c/tag_c.cpp @@ -260,7 +260,7 @@ void taglib_tag_free_strings() if(!stringManagementEnabled) return; - for(List::Iterator it = strings.begin(); it != strings.end(); ++it) + for(List::ConstIterator it = strings.begin(); it != strings.end(); ++it) free(*it); strings.clear(); } diff --git a/cmake/TestFloatFormat.c b/cmake/TestFloatFormat.c index 5f18aafb..4a7b32e4 100644 --- a/cmake/TestFloatFormat.c +++ b/cmake/TestFloatFormat.c @@ -1,5 +1,7 @@ -int main() +int main(int argc, char **argv) { + int ret = 0; + double bin1[] = { // "*TAGLIB*" encoded as a little-endian floating-point number (double)3.9865557444897601e-105, (double)0.0 @@ -8,6 +10,8 @@ int main() // "*TL*" encoded as a little-endian floating-point number (float)1.81480400e-013, (float)0.0 }; + ret += ((int*)bin1)[argc]; + ret += ((int*)bin2)[argc]; - return 0; + return ret; } diff --git a/cmake/modules/TestFloatFormat.cmake b/cmake/modules/TestFloatFormat.cmake index 0e90cde6..c1bc568f 100644 --- a/cmake/modules/TestFloatFormat.cmake +++ b/cmake/modules/TestFloatFormat.cmake @@ -2,12 +2,13 @@ MACRO(TEST_FLOAT_FORMAT FP_IEEE754) IF(NOT FP_IEEE754) - TRY_COMPILE(HAVE_${FP_IEEE754} "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestFloatFormat.c" + TRY_COMPILE(HAVE_FLOAT_FORMAT_BIN + "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestFloatFormat.c" COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin") SET(FP_IEEE754 0) - IF(HAVE_${FP_IEEE754}) + IF(HAVE_FLOAT_FORMAT_BIN) # dont match first/last letter because of string rounding errors :-) FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin" diff --git a/config.h.cmake b/config.h.cmake index 3efbfa72..12dabcfa 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -8,6 +8,18 @@ /* 1 if little-endian, 2 if big-endian. */ #cmakedefine FLOAT_BYTEORDER ${FLOAT_BYTEORDER} +/* Defined if your compiler supports some atomic operations */ +#cmakedefine HAVE_STD_ATOMIC 1 +#cmakedefine HAVE_BOOST_ATOMIC 1 +#cmakedefine HAVE_GCC_ATOMIC 1 +#cmakedefine HAVE_MAC_ATOMIC 1 +#cmakedefine HAVE_WIN_ATOMIC 1 +#cmakedefine HAVE_IA64_ATOMIC 1 + +/* Defined if your compiler supports shared_ptr */ +#cmakedefine HAVE_STD_SMART_PTR 1 +#cmakedefine HAVE_BOOST_SMART_PTR 1 + /* Defined if your compiler supports some byte swap functions */ #cmakedefine HAVE_GCC_BYTESWAP_16 1 #cmakedefine HAVE_GCC_BYTESWAP_32 1 @@ -17,23 +29,6 @@ #cmakedefine HAVE_MAC_BYTESWAP 1 #cmakedefine HAVE_OPENBSD_BYTESWAP 1 -/* Defined if your compiler supports shared_ptr */ -#cmakedefine HAVE_STD_SHARED_PTR 1 // #include / std::shared_ptr -#cmakedefine HAVE_TR1_SHARED_PTR 1 // #include / std::tr1::shared_ptr -#cmakedefine HAVE_BOOST_SHARED_PTR 1 // #include / boost::shared_ptr - -/* Defined if your compiler supports unique_ptr or scoped_ptr */ -#cmakedefine HAVE_STD_UNIQUE_PTR 1 // #include / std::unique_ptr -#cmakedefine HAVE_BOOST_SCOPED_PTR 1 // #include / boost::scoped_ptr - -/* Defined if your compiler supports some atomic operations */ -#cmakedefine HAVE_STD_ATOMIC 1 -#cmakedefine HAVE_BOOST_ATOMIC 1 -#cmakedefine HAVE_GCC_ATOMIC 1 -#cmakedefine HAVE_MAC_ATOMIC 1 -#cmakedefine HAVE_WIN_ATOMIC 1 -#cmakedefine HAVE_IA64_ATOMIC 1 - /* Defined if your compiler supports snprintf or sprintf_s. */ #cmakedefine HAVE_SNPRINTF 1 #cmakedefine HAVE_SPRINTF_S 1 diff --git a/examples/tagwriter.cpp b/examples/tagwriter.cpp index 63163fbe..f2896d76 100644 --- a/examples/tagwriter.cpp +++ b/examples/tagwriter.cpp @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) char field = argv[i][1]; TagLib::String value = argv[i + 1]; - TagLib::List::Iterator it; + TagLib::List::ConstIterator it; for(it = fileList.begin(); it != fileList.end(); ++it) { TagLib::Tag *t = (*it).tag(); @@ -131,7 +131,7 @@ int main(int argc, char *argv[]) usage(); } - TagLib::List::Iterator it; + TagLib::List::ConstIterator it; for(it = fileList.begin(); it != fileList.end(); ++it) (*it).file()->save(); diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp index f7bdcf3d..6410013a 100644 --- a/taglib/ape/apetag.cpp +++ b/taglib/ape/apetag.cpp @@ -236,7 +236,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps) toRemove.append(remIt->first); } - for (StringList::Iterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++) + for(StringList::ConstIterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++) removeItem(*removeIt); // now sync in the "forward direction" diff --git a/taglib/mod/modtag.cpp b/taglib/mod/modtag.cpp index 14c4c741..4ba72117 100644 --- a/taglib/mod/modtag.cpp +++ b/taglib/mod/modtag.cpp @@ -158,7 +158,7 @@ PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) // for each tag that has been set above, remove the first entry in the corresponding // value list. The others will be returned as unsupported by this format. - for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { + for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { if(properties[*it].size() == 1) properties.erase(*it); else diff --git a/taglib/mp4/mp4tag.cpp b/taglib/mp4/mp4tag.cpp index 9b26bcb8..ac92b508 100644 --- a/taglib/mp4/mp4tag.cpp +++ b/taglib/mp4/mp4tag.cpp @@ -612,11 +612,11 @@ MP4::Tag::saveExisting(ByteVector &data, AtomList &path) long length = ilst->length; MP4::Atom *meta = path[path.size() - 2]; - AtomList::Iterator index = meta->children.find(ilst); + AtomList::ConstIterator index = meta->children.find(ilst); // check if there is an atom before 'ilst', and possibly use it as padding if(index != meta->children.begin()) { - AtomList::Iterator prevIndex = index; + AtomList::ConstIterator prevIndex = index; prevIndex--; MP4::Atom *prev = *prevIndex; if(prev->name == "free") { @@ -625,7 +625,7 @@ MP4::Tag::saveExisting(ByteVector &data, AtomList &path) } } // check if there is an atom after 'ilst', and possibly use it as padding - AtomList::Iterator nextIndex = index; + AtomList::ConstIterator nextIndex = index; nextIndex++; if(nextIndex != meta->children.end()) { MP4::Atom *next = *nextIndex; diff --git a/taglib/mpeg/id3v2/frames/chapterframe.cpp b/taglib/mpeg/id3v2/frames/chapterframe.cpp index 1f7a4a07..8e08f315 100644 --- a/taglib/mpeg/id3v2/frames/chapterframe.cpp +++ b/taglib/mpeg/id3v2/frames/chapterframe.cpp @@ -68,7 +68,7 @@ ChapterFrame::ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT d->startOffset = sO; d->endOffset = eO; FrameList l = eF; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) addEmbeddedFrame(*it); d->factory = FrameFactory::instance(); } @@ -169,7 +169,7 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) { FrameList l = d->embeddedFrameListMap[id]; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) removeEmbeddedFrame(*it, true); } @@ -251,7 +251,7 @@ ByteVector ChapterFrame::renderFields() const data.append(ByteVector::fromUInt32BE(d->startOffset)); data.append(ByteVector::fromUInt32BE(d->endOffset)); FrameList l = d->embeddedFrameList; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) data.append((*it)->render()); return data; diff --git a/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp b/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp index ad50c654..24d95849 100644 --- a/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp +++ b/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp @@ -63,7 +63,7 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVect d->elementID = eID; d->childElements = ch; FrameList l = eF; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) addEmbeddedFrame(*it); d->factory = FrameFactory::instance(); } @@ -170,7 +170,7 @@ void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id) { FrameList l = d->embeddedFrameListMap[id]; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) removeEmbeddedFrame(*it, true); } @@ -278,7 +278,7 @@ ByteVector TableOfContentsFrame::renderFields() const it++; } FrameList l = d->embeddedFrameList; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) data.append((*it)->render()); return data; diff --git a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp index 521355db..9bdfecc2 100644 --- a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp @@ -214,12 +214,12 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) // append those split values to the list and make sure that the new string's // type is the same specified for this frame - for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) { + for(ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) { if(!(*it).isEmpty()) { if(d->textEncoding == String::Latin1) d->fieldList.append(Tag::latin1StringHandler()->parse(*it)); else - d->fieldList.append(String(*it, d->textEncoding)); + d->fieldList.append(String(*it, d->textEncoding)); } } } @@ -397,7 +397,7 @@ UserTextIdentificationFrame *UserTextIdentificationFrame::find( ID3v2::Tag *tag, const String &description) // static { FrameList l = tag->frameList("TXXX"); - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) { + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { UserTextIdentificationFrame *f = dynamic_cast(*it); if(f && f->description() == description) return f; diff --git a/taglib/mpeg/id3v2/frames/urllinkframe.cpp b/taglib/mpeg/id3v2/frames/urllinkframe.cpp index fe5b04ee..a8169ec5 100644 --- a/taglib/mpeg/id3v2/frames/urllinkframe.cpp +++ b/taglib/mpeg/id3v2/frames/urllinkframe.cpp @@ -169,7 +169,7 @@ PropertyMap UserUrlLinkFrame::asProperties() const UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static { FrameList l = tag->frameList("WXXX"); - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) { + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { UserUrlLinkFrame *f = dynamic_cast(*it); if(f && f->description() == description) return f; diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index 219971d7..6e305438 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -268,22 +268,22 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) if(frameID == "PRIV") return new PrivateFrame(data, header); - + // Ownership (frames 4.22) - + if(frameID == "OWNE") { OwnershipFrame *f = new OwnershipFrame(data, header); d->setTextEncoding(f); return f; } - + // Chapter (ID3v2 chapters 1.0) - + if(frameID == "CHAP") return new ChapterFrame(data, header); - + // Table of contents (ID3v2 chapters 1.0) - + if(frameID == "CTOC") return new TableOfContentsFrame(data, header); @@ -458,7 +458,7 @@ void FrameFactory::updateGenre(TextIdentificationFrame *frame) const StringList fields = frame->fieldList(); StringList newfields; - for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) { + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { String s = *it; const size_t end = s.find(")"); diff --git a/taglib/mpeg/id3v2/id3v2header.cpp b/taglib/mpeg/id3v2/id3v2header.cpp index ad6b3aa7..10381053 100644 --- a/taglib/mpeg/id3v2/id3v2header.cpp +++ b/taglib/mpeg/id3v2/id3v2header.cpp @@ -215,7 +215,7 @@ void Header::parse(const ByteVector &data) return; } - for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) { + for(ByteVector::ConstIterator it = sizeData.begin(); it != sizeData.end(); it++) { if(uchar(*it) >= 128) { d->tagSize = 0; debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128."); diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp index a3bd3192..9a5809e3 100644 --- a/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/taglib/mpeg/id3v2/id3v2tag.cpp @@ -367,7 +367,7 @@ void ID3v2::Tag::removeFrame(Frame *frame, bool del) void ID3v2::Tag::removeFrames(const ByteVector &id) { FrameList l = d->frameListMap[id]; - for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) removeFrame(*it, true); } @@ -480,7 +480,7 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const ID3v2::TextIdentificationFrame *frameTDRC = 0; ID3v2::TextIdentificationFrame *frameTIPL = 0; ID3v2::TextIdentificationFrame *frameTMCL = 0; - for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) { + for(FrameList::ConstIterator it = d->frameList.begin(); it != d->frameList.end(); it++) { ID3v2::Frame *frame = *it; ByteVector frameID = frame->header()->frameID(); for(int i = 0; unsupportedFrames[i]; i++) { @@ -594,7 +594,7 @@ ByteVector ID3v2::Tag::render(int version) const downgradeFrames(&frameList, &newFrames); } - for(FrameList::Iterator it = frameList.begin(); it != frameList.end(); it++) { + for(FrameList::ConstIterator it = frameList.begin(); it != frameList.end(); it++) { (*it)->header()->setVersion(version); if((*it)->header()->frameID().size() != 4) { debug("A frame of unsupported or unknown type \'" diff --git a/taglib/ogg/oggfile.cpp b/taglib/ogg/oggfile.cpp index bf857080..2dff9592 100644 --- a/taglib/ogg/oggfile.cpp +++ b/taglib/ogg/oggfile.cpp @@ -354,7 +354,7 @@ void Ogg::File::writePageGroup(const List &thePageGroup) // create a gap for the new pages int numberOfNewPages = pages.back()->header()->pageSequenceNumber() - pageGroup.back(); - List::Iterator pageIter = d->pages.begin(); + List::ConstIterator pageIter = d->pages.begin(); for(int i = 0; i < pageGroup.back(); i++) { if(pageIter != d->pages.end()) { ++pageIter; diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index 34dde282..958f1cae 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -246,22 +246,24 @@ void RIFF::File::removeChunk(uint i) { if(i >= d->chunks.size()) return; - - removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8); - d->chunks.erase(d->chunks.begin() + i); + + std::vector::iterator it = d->chunks.begin(); + std::advance(it, i); + + const uint removeSize = it->size + it->padding + 8; + removeBlock(it->offset - 8, removeSize); + it = d->chunks.erase(it); + + for(; it != d->chunks.end(); ++it) + it->offset -= removeSize; } void RIFF::File::removeChunk(const ByteVector &name) { - std::vector newChunks; - for(size_t i = 0; i < d->chunks.size(); ++i) { + for(int i = d->chunks.size() - 1; i >= 0; --i) { if(d->chunks[i].name == name) - removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8); - else - newChunks.push_back(d->chunks[i]); + removeChunk(i); } - - d->chunks.swap(newChunks); } //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/riff/wav/wavfile.cpp b/taglib/riff/wav/wavfile.cpp index 882c7ed5..25ad7ec2 100644 --- a/taglib/riff/wav/wavfile.cpp +++ b/taglib/riff/wav/wavfile.cpp @@ -147,24 +147,20 @@ bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version) strip(static_cast(AllTags & ~tags)); ID3v2::Tag *id3v2tag = d->tag.access(ID3v2Index, false); - if(!id3v2tag->isEmpty()) { - if(tags & ID3v2) { - setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version)); - d->hasID3v2 = true; - } + if((tags & ID3v2) && !id3v2tag->isEmpty()) { + setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version)); + d->hasID3v2 = true; } Info::Tag *infotag = d->tag.access(InfoIndex, false); - if(!infotag->isEmpty()) { - if(tags & Info) { - int chunkId = findInfoTagChunk(); - if(chunkId != -1) - setChunkData(chunkId, infotag->render()); - else - setChunkData("LIST", infotag->render(), true); + if((tags & Info) && !infotag->isEmpty()) { + int chunkId = findInfoTagChunk(); + if(chunkId != -1) + setChunkData(chunkId, infotag->render()); + else + setChunkData("LIST", infotag->render(), true); - d->hasInfo = true; - } + d->hasInfo = true; } return true; @@ -222,13 +218,17 @@ void RIFF::WAV::File::read(bool readProperties, AudioProperties::ReadStyle prope void RIFF::WAV::File::strip(TagTypes tags) { - if(tags & ID3v2) + if(tags & ID3v2) { removeChunk(d->tagChunkID); + d->hasID3v2 = false; + } if(tags & Info){ TagLib::uint chunkId = findInfoTagChunk(); - if(chunkId != TagLib::uint(-1)) + if(chunkId != TagLib::uint(-1)) { removeChunk(chunkId); + d->hasInfo = false; + } } } diff --git a/taglib/tag.cpp b/taglib/tag.cpp index 17dcca5c..bcb913d7 100644 --- a/taglib/tag.cpp +++ b/taglib/tag.cpp @@ -141,7 +141,7 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps) // for each tag that has been set above, remove the first entry in the corresponding // value list. The others will be returned as unsupported by this format. - for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { + for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { if(properties[*it].size() == 1) properties.erase(*it); else diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index b1669a99..1a19c663 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -161,15 +161,12 @@ size_t findVector( lastOccurrence[static_cast(*(patternBegin + i))] = patternSize - i - 1; TIterator it = dataBegin + patternSize - 1 + offset; - while(true) - { + while(true) { TIterator itBuffer = it; TIterator itPattern = patternBegin + patternSize - 1; - while(*itBuffer == *itPattern) - { - if(itPattern == patternBegin) - { + while(*itBuffer == *itPattern) { + if(itPattern == patternBegin) { if((itBuffer - dataBegin - offset) % byteAlign == 0) return (itBuffer - dataBegin); else @@ -193,32 +190,27 @@ size_t findVector( template inline T toNumber(const ByteVector &v, size_t offset) { - static const bool swap = (ENDIAN != Utils::SystemByteOrder); - - if(LENGTH >= sizeof(T) && offset + LENGTH <= v.size()) - { + if(LENGTH == sizeof(T) && offset + LENGTH <= v.size()) { // Uses memcpy instead of reinterpret_cast to avoid an alignment exception. T tmp; ::memcpy(&tmp, v.data() + offset, sizeof(T)); - if(swap) + if(ENDIAN != Utils::SystemByteOrder) return Utils::byteSwap(tmp); else return tmp; } - else if(offset < v.size()) - { + else if(offset < v.size()) { const size_t length = std::min(LENGTH, v.size() - offset); T sum = 0; - for(size_t i = 0; i < length; i++) { - const size_t shift = (swap ? length - 1 - i : i) * 8; + for(size_t i = 0; i < length; ++i) { + const size_t shift = (ENDIAN == BigEndian ? length - 1 - i : i) * 8; sum |= static_cast(static_cast(v[offset + i])) << shift; } return sum; } - else - { + else { debug("toNumber() - offset is out of range. Returning 0."); return 0; } @@ -236,7 +228,7 @@ inline ByteVector fromNumber(T value) template TFloat toFloat(const ByteVector &v, size_t offset) { - if (offset > v.size() - sizeof(TInt)) { + if(offset > v.size() - sizeof(TInt)) { debug("toFloat() - offset is out of range. Returning 0."); return 0.0; } @@ -657,7 +649,8 @@ ByteVector &ByteVector::resize(size_t size, char padding) ByteVector::Iterator ByteVector::begin() { - return d->data->begin() + d->offset; + detach(); + return d->data->begin(); } ByteVector::ConstIterator ByteVector::begin() const @@ -667,7 +660,8 @@ ByteVector::ConstIterator ByteVector::begin() const ByteVector::Iterator ByteVector::end() { - return d->data->begin() + d->offset + d->length; + detach(); + return d->data->end(); } ByteVector::ConstIterator ByteVector::end() const @@ -677,26 +671,24 @@ ByteVector::ConstIterator ByteVector::end() const ByteVector::ReverseIterator ByteVector::rbegin() { - std::vector &v = *(d->data); - return v.rbegin() + (v.size() - (d->offset + d->length)); + detach(); + return d->data->rbegin(); } ByteVector::ConstReverseIterator ByteVector::rbegin() const { - std::vector &v = *(d->data); - return v.rbegin() + (v.size() - (d->offset + d->length)); + return d->data->rbegin() + (d->data->size() - (d->offset + d->length)); } ByteVector::ReverseIterator ByteVector::rend() { - std::vector &v = *(d->data); - return v.rbegin() + (v.size() - d->offset); + detach(); + return d->data->rend(); } ByteVector::ConstReverseIterator ByteVector::rend() const { - std::vector &v = *(d->data); - return v.rbegin() + (v.size() - d->offset); + return d->data->rbegin() + (d->data->size() - d->offset); } bool ByteVector::isNull() const diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp index 6f59f568..f4ae4278 100644 --- a/taglib/toolkit/tfilestream.cpp +++ b/taglib/toolkit/tfilestream.cpp @@ -175,7 +175,7 @@ FileName FileStream::name() const ByteVector FileStream::readBlock(size_t length) { if(!isOpen()) { - debug("File::readBlock() -- invalid file."); + debug("FileStream::readBlock() -- invalid file."); return ByteVector::null; } @@ -197,12 +197,12 @@ ByteVector FileStream::readBlock(size_t length) void FileStream::writeBlock(const ByteVector &data) { if(!isOpen()) { - debug("File::writeBlock() -- invalid file."); + debug("FileStream::writeBlock() -- invalid file."); return; } if(readOnly()) { - debug("File::writeBlock() -- read only file."); + debug("FileStream::writeBlock() -- read only file."); return; } @@ -212,12 +212,12 @@ void FileStream::writeBlock(const ByteVector &data) void FileStream::insert(const ByteVector &data, offset_t start, size_t replace) { if(!isOpen()) { - debug("File::insert() -- invalid file."); + debug("FileStream::insert() -- invalid file."); return; } if(readOnly()) { - debug("File::insert() -- read only file."); + debug("FileStream::insert() -- read only file."); return; } @@ -294,7 +294,7 @@ void FileStream::insert(const ByteVector &data, offset_t start, size_t replace) void FileStream::removeBlock(offset_t start, size_t length) { if(!isOpen()) { - debug("File::removeBlock() -- invalid file."); + debug("FileStream::removeBlock() -- invalid file."); return; } @@ -341,7 +341,7 @@ bool FileStream::isOpen() const void FileStream::seek(offset_t offset, Position p) { if(!isOpen()) { - debug("File::seek() -- invalid file."); + debug("FileStream::seek() -- invalid file."); return; } @@ -373,7 +373,7 @@ void FileStream::seek(offset_t offset, Position p) SetFilePointer(d->file, 0, NULL, FILE_BEGIN); } if(GetLastError() != NO_ERROR) { - debug("File::seek() -- Failed to set the file pointer."); + debug("FileStream::seek() -- Failed to set the file pointer."); } #else @@ -426,7 +426,7 @@ offset_t FileStream::tell() const return position.QuadPart; } else { - debug("File::tell() -- Failed to get the file pointer."); + debug("FileStream::tell() -- Failed to get the file pointer."); return 0; } @@ -440,7 +440,7 @@ offset_t FileStream::tell() const offset_t FileStream::length() { if(!isOpen()) { - debug("File::length() -- invalid file."); + debug("FileStream::length() -- invalid file."); return 0; } @@ -455,7 +455,7 @@ offset_t FileStream::length() return fileSize.QuadPart; } else { - debug("File::length() -- Failed to get the file size."); + debug("FileStream::length() -- Failed to get the file size."); return 0; } @@ -493,7 +493,7 @@ void FileStream::truncate(offset_t length) SetLastError(NO_ERROR); SetEndOfFile(d->file); if(GetLastError() != NO_ERROR) { - debug("File::truncate() -- Failed to truncate the file."); + debug("FileStream::truncate() -- Failed to truncate the file."); } seek(currentPos); diff --git a/taglib/toolkit/tlist.tcc b/taglib/toolkit/tlist.tcc index a9e74a61..a7890858 100644 --- a/taglib/toolkit/tlist.tcc +++ b/taglib/toolkit/tlist.tcc @@ -239,6 +239,7 @@ template template typename List::Iterator List::find(const U &value) { + detach(); return std::find(d->list.begin(), d->list.end(), value); } diff --git a/taglib/toolkit/tpropertymap.cpp b/taglib/toolkit/tpropertymap.cpp index 3317cc92..313d7fb4 100644 --- a/taglib/toolkit/tpropertymap.cpp +++ b/taglib/toolkit/tpropertymap.cpp @@ -154,12 +154,12 @@ String PropertyMap::toString() const void PropertyMap::removeEmpty() { - StringList emptyKeys; - for(Iterator it = begin(); it != end(); ++it) - if(it->second.isEmpty()) - emptyKeys.append(it->first); - for(StringList::Iterator emptyIt = emptyKeys.begin(); emptyIt != emptyKeys.end(); emptyIt++ ) - erase(*emptyIt); + PropertyMap m; + for(ConstIterator it = begin(); it != end(); ++it) { + if(!it->second.isEmpty()) + m.insert(it->first, it->second); + } + *this = m; } StringList &PropertyMap::unsupportedData() diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 389c6eb9..c272a610 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #ifdef HAVE_STD_CODECVT # include @@ -70,7 +72,7 @@ namespace st, srcBegin, srcEnd, source, dstBegin, dstEnd, target); if(result != utf8_utf16_t::ok) { - debug("String::copyFromUTF8() - Unicode conversion error."); + debug("String::UTF16toUTF8() - Unicode conversion error."); } #else @@ -88,7 +90,7 @@ namespace &srcBegin, srcEnd, &dstBegin, dstEnd, Unicode::lenientConversion); if(result != Unicode::conversionOK) { - debug("String::to8Bit() - Unicode conversion error."); + debug("String::UTF16toUTF8() - Unicode conversion error."); } #endif @@ -116,7 +118,7 @@ namespace st, srcBegin, srcEnd, source, dstBegin, dstEnd, target); if(result != utf8_utf16_t::ok) { - debug("String::copyFromUTF8() - Unicode conversion error."); + debug("String::UTF8toUTF16() - Unicode conversion error."); } #else @@ -134,7 +136,7 @@ namespace &srcBegin, srcEnd, &dstBegin, dstEnd, Unicode::lenientConversion); if(result != Unicode::conversionOK) { - debug("String::copyFromUTF8() - Unicode conversion error."); + debug("String::UTF8toUTF16() - Unicode conversion error."); } #endif @@ -185,7 +187,7 @@ String::String(const std::string &s, Type t) : else if(t == String::UTF8) copyFromUTF8(s.c_str(), s.length()); else { - debug("String::String() -- A std::string should not contain UTF16."); + debug("String::String() -- std::string should not contain UTF16."); } } @@ -195,7 +197,7 @@ String::String(const std::wstring &s, Type t) : if(t == UTF16 || t == UTF16BE || t == UTF16LE) copyFromUTF16(s.c_str(), s.length(), t); else { - debug("String::String() -- A TagLib::std::wstring should not contain Latin1 or UTF-8."); + debug("String::String() -- std::wstring should not contain Latin1 or UTF-8."); } } @@ -205,7 +207,7 @@ String::String(const wchar_t *s, Type t) : if(t == UTF16 || t == UTF16BE || t == UTF16LE) copyFromUTF16(s, ::wcslen(s), t); else { - debug("String::String() -- A const wchar_t * should not contain Latin1 or UTF-8."); + debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8."); } } @@ -217,7 +219,7 @@ String::String(const char *s, Type t) : else if(t == String::UTF8) copyFromUTF8(s, ::strlen(s)); else { - debug("String::String() -- A const char * should not contain UTF16."); + debug("String::String() -- const char * should not contain UTF16."); } } @@ -227,7 +229,7 @@ String::String(wchar_t c, Type t) : if(t == UTF16 || t == UTF16BE || t == UTF16LE) copyFromUTF16(&c, 1, t); else { - debug("String::String() -- A wchar_t should not contain Latin1 or UTF-8."); + debug("String::String() -- wchar_t should not contain Latin1 or UTF-8."); } } @@ -239,7 +241,7 @@ String::String(char c, Type t) : else if(t == String::UTF8) copyFromUTF8(&c, 1); else { - debug("String::String() -- A char should not contain UTF16."); + debug("String::String() -- char should not contain UTF16."); } } @@ -291,6 +293,7 @@ const wchar_t *String::toCWString() const String::Iterator String::begin() { + detach(); return d->data->begin(); } @@ -301,6 +304,7 @@ String::ConstIterator String::begin() const String::Iterator String::end() { + detach(); return d->data->end(); } @@ -322,16 +326,13 @@ size_t String::rfind(const String &s, size_t offset) const StringList String::split(const String &separator) const { StringList list; - for(size_t index = 0;;) - { + for(size_t index = 0;;) { const size_t sep = find(separator, index); - if(sep == npos) - { + if(sep == npos) { list.append(substr(index, size() - index)); break; } - else - { + else { list.append(substr(index, sep - index)); index = sep + separator.size(); } @@ -472,13 +473,18 @@ int String::toInt(bool *ok) const { const wchar_t *begin = d->data->c_str(); wchar_t *end; - const int value = static_cast(::wcstol(begin, &end, 10)); + errno = 0; + const long value = ::wcstol(begin, &end, 10); - // Has wcstol() consumed the entire string? - if(ok) - *ok = (end > begin && *end == L'\0'); + // Has wcstol() consumed the entire string and not overflowed? + if(ok) { + *ok = (errno == 0 && end > begin && *end == L'\0'); +#if LONG_MAX > INT_MAX + *ok = (*ok && value > INT_MIN && value < INT_MAX); +#endif + } - return value; + return static_cast(value); } String String::stripWhiteSpace() const @@ -532,24 +538,35 @@ bool String::operator==(const String &s) const return (d->data == s.d->data || *d->data == *s.d->data); } +bool String::operator!=(const String &s) const +{ + return !(*this == s); +} + bool String::operator==(const char *s) const { - for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) { - if(*it != static_cast(*s++)) + const wchar_t *p = toCWString(); + + while(*p != L'\0' || *s != '\0') { + if(*p++ != static_cast(*s++)) return false; } - return true; } +bool String::operator!=(const char *s) const +{ + return !(*this == s); +} + bool String::operator==(const wchar_t *s) const { return (*d->data == s); } -bool String::operator!=(const String &s) const +bool String::operator!=(const wchar_t *s) const { - return !operator==(s); + return !(*this == s); } String &String::operator+=(const String &s) diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index be5a9007..eeb96bcd 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -342,9 +342,9 @@ namespace TagLib { /*! * Convert the string to an integer. * - * If the conversion was successfull, it sets the value of \a *ok to - * true and returns the integer. Otherwise it sets \a *ok to false - * and the result is undefined. + * If the conversion was successful, it sets the value of \a *ok to true and + * returns the integer. Otherwise it sets \a *ok to false and the result is + * undefined. */ int toInt(bool *ok = 0) const; @@ -385,11 +385,23 @@ namespace TagLib { bool operator==(const String &s) const; /*! - * Compares each character of the String with each character in \a s and + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const String &s) const; + + /*! + * Compares each character of the String with each character of \a s and * returns true if the strings match. */ bool operator==(const char *s) const; + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const char *s) const; + /*! * Compares each character of the String with each character of \a s and * returns true if the strings match. @@ -400,7 +412,7 @@ namespace TagLib { * Compares each character of the String with each character of \a s and * returns false if the strings match. */ - bool operator!=(const String &s) const; + bool operator!=(const wchar_t *s) const; /*! * Appends \a s to the end of the String. diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp index 18b01bf3..031f8a1e 100644 --- a/taglib/xm/xmfile.cpp +++ b/taglib/xm/xmfile.cpp @@ -341,7 +341,7 @@ namespace uint read(TagLib::File &file, uint limit) { uint sumcount = 0; - for(List::Iterator i = m_readers.begin(); + for(List::ConstIterator i = m_readers.begin(); limit > 0 && i != m_readers.end(); ++ i) { uint count = (*i)->read(file, limit); limit -= count; diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp index ed46c2ed..bca51748 100644 --- a/tests/test_bytevector.cpp +++ b/tests/test_bytevector.cpp @@ -41,6 +41,7 @@ class TestByteVector : public CppUnit::TestFixture CPPUNIT_TEST(testToHex); CPPUNIT_TEST(testNumericCoversion); CPPUNIT_TEST(testReplace); + CPPUNIT_TEST(testIterator); CPPUNIT_TEST_SUITE_END(); public: @@ -274,6 +275,36 @@ public: } } + void testIterator() + { + ByteVector v1("taglib"); + ByteVector v2 = v1; + + ByteVector::Iterator it1 = v1.begin(); + ByteVector::Iterator it2 = v2.begin(); + + CPPUNIT_ASSERT_EQUAL('t', *it1); + CPPUNIT_ASSERT_EQUAL('t', *it2); + + std::advance(it1, 4); + std::advance(it2, 4); + *it2 = 'I'; + CPPUNIT_ASSERT_EQUAL('i', *it1); + CPPUNIT_ASSERT_EQUAL('I', *it2); + + ByteVector::ReverseIterator it3 = v1.rbegin(); + ByteVector::ReverseIterator it4 = v2.rbegin(); + + CPPUNIT_ASSERT_EQUAL('b', *it3); + CPPUNIT_ASSERT_EQUAL('b', *it4); + + std::advance(it3, 4); + std::advance(it4, 4); + *it4 = 'A'; + CPPUNIT_ASSERT_EQUAL('a', *it3); + CPPUNIT_ASSERT_EQUAL('A', *it4); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector); diff --git a/tests/test_list.cpp b/tests/test_list.cpp index 39cbaf0a..1b3156b5 100644 --- a/tests/test_list.cpp +++ b/tests/test_list.cpp @@ -51,8 +51,13 @@ public: l3.append(3); l3.append(4); CPPUNIT_ASSERT(l1 == l3); + + List l4 = l1; + List::Iterator it = l4.find(3); + *it = 33; + CPPUNIT_ASSERT_EQUAL(l1[2], 3); + CPPUNIT_ASSERT_EQUAL(l4[2], 33); } - }; CPPUNIT_TEST_SUITE_REGISTRATION(TestList); diff --git a/tests/test_map.cpp b/tests/test_map.cpp index b6f77aae..5fdea157 100644 --- a/tests/test_map.cpp +++ b/tests/test_map.cpp @@ -15,11 +15,21 @@ public: void testInsert() { - Map m; - m.insert("foo", 3); - CPPUNIT_ASSERT_EQUAL(3, m["foo"]); - m.insert("foo", 7); - CPPUNIT_ASSERT_EQUAL(7, m["foo"]); + Map m1; + m1.insert("foo", 3); + CPPUNIT_ASSERT_EQUAL(3, m1["foo"]); + m1.insert("foo", 7); + CPPUNIT_ASSERT_EQUAL(7, m1["foo"]); + + m1.insert("alice", 5); + m1.insert("bob", 9); + m1.insert("carol", 11); + + Map m2 = m1; + Map::Iterator it = m2.find("bob"); + (*it).second = 99; + CPPUNIT_ASSERT_EQUAL(m1["bob"], 9); + CPPUNIT_ASSERT_EQUAL(m2["bob"], 99); } }; diff --git a/tests/test_ogg.cpp b/tests/test_ogg.cpp index 8a494a14..61b96701 100644 --- a/tests/test_ogg.cpp +++ b/tests/test_ogg.cpp @@ -88,12 +88,17 @@ public: CPPUNIT_ASSERT_EQUAL(size_t(2), tags["UNUSUALTAG"].size()); CPPUNIT_ASSERT_EQUAL(String("usual value"), tags["UNUSUALTAG"][0]); CPPUNIT_ASSERT_EQUAL(String("another value"), tags["UNUSUALTAG"][1]); - CPPUNIT_ASSERT_EQUAL(String("öäüoΣø", String::UTF8), tags["UNICODETAG"][0]); + CPPUNIT_ASSERT_EQUAL( + String("\xC3\xB6\xC3\xA4\xC3\xBC\x6F\xCE\xA3\xC3\xB8", String::UTF8), + tags["UNICODETAG"][0]); - tags["UNICODETAG"][0] = String("νεω ναλυε", String::UTF8); + tags["UNICODETAG"][0] = String( + "\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8); tags.erase("UNUSUALTAG"); f->tag()->setProperties(tags); - CPPUNIT_ASSERT_EQUAL(String("νεω ναλυε", String::UTF8), f->tag()->properties()["UNICODETAG"][0]); + CPPUNIT_ASSERT_EQUAL( + String("\xCE\xBD\xCE\xB5\xCF\x89\x20\xCE\xBD\xCE\xB1\xCE\xBB\xCF\x85\xCE\xB5", String::UTF8), + f->tag()->properties()["UNICODETAG"][0]); CPPUNIT_ASSERT_EQUAL(false, f->tag()->properties().contains("UNUSUALTAG")); delete f; diff --git a/tests/test_riff.cpp b/tests/test_riff.cpp index eba926c5..be9e8570 100644 --- a/tests/test_riff.cpp +++ b/tests/test_riff.cpp @@ -20,12 +20,17 @@ public: TagLib::uint chunkDataSize(TagLib::uint i) { return RIFF::File::chunkDataSize(i); }; ByteVector chunkName(TagLib::uint i) { return RIFF::File::chunkName(i); }; ByteVector chunkData(TagLib::uint i) { return RIFF::File::chunkData(i); }; + void setChunkData(uint i, const ByteVector &data) { + RIFF::File::setChunkData(i, data); + } void setChunkData(const ByteVector &name, const ByteVector &data) { RIFF::File::setChunkData(name, data); }; virtual TagLib::Tag* tag() const { return 0; }; virtual TagLib::AudioProperties* audioProperties() const { return 0;}; virtual bool save() { return false; }; + void removeChunk(uint i) { RIFF::File::removeChunk(i); } + void removeChunk(const ByteVector &name) { RIFF::File::removeChunk(name); } }; class TestRIFF : public CppUnit::TestFixture @@ -35,6 +40,7 @@ class TestRIFF : public CppUnit::TestFixture CPPUNIT_TEST(testLastChunkAtEvenPosition); CPPUNIT_TEST(testLastChunkAtEvenPosition2); CPPUNIT_TEST(testLastChunkAtEvenPosition3); + CPPUNIT_TEST(testChunkOffset); CPPUNIT_TEST_SUITE_END(); public: @@ -193,6 +199,63 @@ public: delete f; } + void testChunkOffset() + { + ScopedFileCopy copy("empty", ".aiff"); + string filename = copy.fileName(); + + PublicRIFF *f = new PublicRIFF(filename.c_str()); + + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->chunkName(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->chunkName(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->chunkName(2)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x1728 + 8), f->chunkOffset(2)); + + const ByteVector data(0x400, ' '); + f->setChunkData("SSND", data); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x042E + 8), f->chunkOffset(2)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4)); + f->seek(f->chunkOffset(2) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->setChunkData(0, data); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x081C + 8), f->chunkOffset(2)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4)); + f->seek(f->chunkOffset(2) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->removeChunk("SSND"); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->removeChunk(0); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestRIFF); diff --git a/tests/test_string.cpp b/tests/test_string.cpp index c42082ec..fede02f7 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -46,6 +46,7 @@ class TestString : public CppUnit::TestFixture CPPUNIT_TEST(testNewline); CPPUNIT_TEST(testUpper); CPPUNIT_TEST(testEncode); + CPPUNIT_TEST(testIterator); CPPUNIT_TEST_SUITE_END(); public: @@ -110,19 +111,6 @@ public: String unicode9(stduni, String::UTF16LE); CPPUNIT_ASSERT(unicode9[1] == (littleEndian ? L'\u672c' : L'\u2c67')); - CPPUNIT_ASSERT(strcmp(String::number(0).toCString(), "0") == 0); - CPPUNIT_ASSERT(strcmp(String::number(12345678).toCString(), "12345678") == 0); - CPPUNIT_ASSERT(strcmp(String::number(-12345678).toCString(), "-12345678") == 0); - - String n = "123"; - CPPUNIT_ASSERT(n.toInt() == 123); - - n = "-123"; - CPPUNIT_ASSERT(n.toInt() == -123); - - CPPUNIT_ASSERT(String("0").toInt() == 0); - CPPUNIT_ASSERT(String("1").toInt() == 1); - CPPUNIT_ASSERT(String(" foo ").stripWhiteSpace() == String("foo")); CPPUNIT_ASSERT(String("foo ").stripWhiteSpace() == String("foo")); CPPUNIT_ASSERT(String(" foo").stripWhiteSpace() == String("foo")); @@ -232,6 +220,12 @@ public: CPPUNIT_ASSERT_EQUAL(String("-123").toInt(&ok), -123); CPPUNIT_ASSERT_EQUAL(ok, true); + CPPUNIT_ASSERT_EQUAL(String("123aa").toInt(&ok), 123); + CPPUNIT_ASSERT_EQUAL(ok, false); + + CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(&ok), -123); + CPPUNIT_ASSERT_EQUAL(ok, false); + CPPUNIT_ASSERT_EQUAL(String("abc").toInt(&ok), 0); CPPUNIT_ASSERT_EQUAL(ok, false); @@ -244,10 +238,8 @@ public: CPPUNIT_ASSERT_EQUAL(String("-").toInt(&ok), 0); CPPUNIT_ASSERT_EQUAL(ok, false); - CPPUNIT_ASSERT_EQUAL(String("123").toInt(), 123); - CPPUNIT_ASSERT_EQUAL(String("-123").toInt(), -123); - CPPUNIT_ASSERT_EQUAL(String("123aa").toInt(), 123); - CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(), -123); + String("9999999999").toInt(&ok); + CPPUNIT_ASSERT_EQUAL(ok, false); } void testFromInt() @@ -324,6 +316,23 @@ public: CPPUNIT_ASSERT(empty7.empty()); } + void testIterator() + { + String s1 = "taglib string"; + String s2 = s1; + + String::Iterator it1 = s1.begin(); + String::Iterator it2 = s2.begin(); + + CPPUNIT_ASSERT_EQUAL(L't', *it1); + CPPUNIT_ASSERT_EQUAL(L't', *it2); + + std::advance(it1, 4); + std::advance(it2, 4); + *it2 = L'I'; + CPPUNIT_ASSERT_EQUAL(L'i', *it1); + CPPUNIT_ASSERT_EQUAL(L'I', *it2); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(TestString); diff --git a/tests/test_wav.cpp b/tests/test_wav.cpp index e42bc916..6446a1c2 100644 --- a/tests/test_wav.cpp +++ b/tests/test_wav.cpp @@ -14,6 +14,7 @@ class TestWAV : public CppUnit::TestFixture CPPUNIT_TEST_SUITE(TestWAV); CPPUNIT_TEST(testLength); CPPUNIT_TEST(testZeroSizeDataChunk); + CPPUNIT_TEST(testStripTags); CPPUNIT_TEST(testFormat); CPPUNIT_TEST_SUITE_END(); @@ -31,7 +32,44 @@ public: RIFF::WAV::File f(TEST_FILE_PATH_C("zero-size-chunk.wav")); CPPUNIT_ASSERT_EQUAL(false, f.isValid()); } - + + void testStripTags() + { + ScopedFileCopy copy("empty", ".wav"); + string filename = copy.fileName(); + + RIFF::WAV::File *f = new RIFF::WAV::File(filename.c_str()); + f->ID3v2Tag()->setTitle("test title"); + f->InfoTag()->setTitle("test title"); + f->save(); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + f->save(RIFF::WAV::File::ID3v2, true); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(!f->hasInfoTag()); + f->ID3v2Tag()->setTitle("test title"); + f->InfoTag()->setTitle("test title"); + f->save(); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + f->save(RIFF::WAV::File::Info, true); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(!f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + delete f; + } + void testFormat() { RIFF::WAV::File f1(TEST_FILE_PATH_C("empty.wav")); @@ -42,7 +80,6 @@ public: CPPUNIT_ASSERT_EQUAL(true, f2.isValid()); CPPUNIT_ASSERT_EQUAL((uint)6, f2.audioProperties()->format()); } - }; CPPUNIT_TEST_SUITE_REGISTRATION(TestWAV);