diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index 1d39a713..323e8091 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -412,10 +412,11 @@ void FrameFactory::updateGenre(TextIdentificationFrame *frame) const if(s.startsWith("(") && end > 0) { // "(12)Genre" String text = s.substr(end + 1); - int number = s.substr(1, end - 1).toInt(); - if (number > 0 && number <= 255 && !(ID3v1::genre(number) == text)) + bool ok; + int number = s.substr(1, end - 1).toInt(&ok); + if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text)) newfields.append(s.substr(1, end - 1)); - if (!text.isEmpty()) + if(!text.isEmpty()) newfields.append(text); } else { diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp index 1d4e8d4c..2ef00270 100644 --- a/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/taglib/mpeg/id3v2/id3v2tag.cpp @@ -164,19 +164,10 @@ String ID3v2::Tag::genre() const if((*it).isEmpty()) continue; - bool isNumber = true; - - for(String::ConstIterator charIt = (*it).begin(); - isNumber && charIt != (*it).end(); - ++charIt) - { - isNumber = *charIt >= '0' && *charIt <= '9'; - } - - if(isNumber) { - int number = (*it).toInt(); - if(number >= 0 && number <= 255) - *it = ID3v1::genre(number); + bool ok; + int number = (*it).toInt(&ok); + if(ok && number >= 0 && number <= 255) { + *it = ID3v1::genre(number); } if(std::find(genres.begin(), genres.end(), *it) == genres.end()) diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 755a8770..876575b6 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -431,18 +431,28 @@ ByteVector String::data(Type t) const } int String::toInt() const +{ + return toInt(0); +} + +int String::toInt(bool *ok) const { int value = 0; - bool negative = d->data[0] == '-'; - uint i = negative ? 1 : 0; + uint size = d->data.size(); + bool negative = size > 0 && d->data[0] == '-'; + uint start = negative ? 1 : 0; + uint i = start; - for(; i < d->data.size() && d->data[i] >= '0' && d->data[i] <= '9'; i++) + for(; i < size && d->data[i] >= '0' && d->data[i] <= '9'; i++) value = value * 10 + (d->data[i] - '0'); if(negative) value = value * -1; + if(ok) + *ok = (size > start && i == size); + return value; } diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index 9289f7da..6534b923 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -291,9 +291,21 @@ namespace TagLib { /*! * Convert the string to an integer. + * + * Returns the integer if the conversion was successfull or 0 if the + * string does not represent a number. */ int toInt() const; + /*! + * 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. + */ + int toInt(bool *ok) const; + /*! * Returns a string with the leading and trailing whitespace stripped. */ diff --git a/tests/test_string.cpp b/tests/test_string.cpp index f677d059..b6ff972e 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -40,6 +40,7 @@ class TestString : public CppUnit::TestFixture CPPUNIT_TEST(testUTF16DecodeEmptyWithBOM); CPPUNIT_TEST(testAppendCharDetach); CPPUNIT_TEST(testAppendStringDetach); + CPPUNIT_TEST(testToInt); CPPUNIT_TEST_SUITE_END(); public: @@ -165,6 +166,33 @@ public: CPPUNIT_ASSERT_EQUAL(3, String("foo.bar").rfind(".")); } + void testToInt() + { + bool ok; + CPPUNIT_ASSERT_EQUAL(String("123").toInt(&ok), 123); + CPPUNIT_ASSERT_EQUAL(ok, true); + + CPPUNIT_ASSERT_EQUAL(String("-123").toInt(&ok), -123); + CPPUNIT_ASSERT_EQUAL(ok, true); + + CPPUNIT_ASSERT_EQUAL(String("abc").toInt(&ok), 0); + CPPUNIT_ASSERT_EQUAL(ok, false); + + CPPUNIT_ASSERT_EQUAL(String("1x").toInt(&ok), 1); + CPPUNIT_ASSERT_EQUAL(ok, false); + + CPPUNIT_ASSERT_EQUAL(String("").toInt(&ok), 0); + CPPUNIT_ASSERT_EQUAL(ok, false); + + 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); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestString);