diff --git a/ChangeLog b/ChangeLog index b47e7bc5..1fc92ec3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-11-22 Tatsuhiro Tsujikawa + + Added FromHex() + * src/util.cc + * src/util.h + * test/UtilTest.cc + 2009-11-22 Tatsuhiro Tsujikawa Added _metadataGetMode member variable. It toggles the action when diff --git a/src/util.cc b/src/util.cc index bf13e526..308d2660 100644 --- a/src/util.cc +++ b/src/util.cc @@ -298,6 +298,41 @@ std::string toHex(const std::string& src) return toHex(reinterpret_cast(src.c_str()), src.size()); } +static unsigned int hexCharToUInt(unsigned char ch) +{ + + if('a' <= ch && ch <= 'f') { + ch -= 'a'; + ch += 10; + } else if('A' <= ch && ch <= 'F') { + ch -= 'A'; + ch += 10; + } else if('0' <= ch && ch <= '9') { + ch -= '0'; + } else { + ch = 255; + } + return ch; +} + +std::string fromHex(const std::string& src) +{ + std::string dest; + if(src.size()%2) { + return dest; + } + for(size_t i = 0; i < src.size(); i += 2) { + unsigned char high = hexCharToUInt(src[i]); + unsigned char low = hexCharToUInt(src[i+1]); + if(high == 255 || low == 255) { + dest.clear(); + return dest; + } + dest += (high*16+low); + } + return dest; +} + FILE* openFile(const std::string& filename, const std::string& mode) { FILE* file = fopen(filename.c_str(), mode.c_str()); return file; diff --git a/src/util.h b/src/util.h index 9ab0e70e..3db8c31a 100644 --- a/src/util.h +++ b/src/util.h @@ -170,6 +170,11 @@ std::string toHex(const char* src, size_t len); std::string toHex(const std::string& src); +// Converts hexadecimal ascii string 'src' into packed binary form and +// return the result. If src is not well formed, then empty string is +// returned. +std::string fromHex(const std::string& src); + FILE* openFile(const std::string& filename, const std::string& mode); bool isPowerOf(int num, int base); diff --git a/test/UtilTest.cc b/test/UtilTest.cc index b27e6181..bb1f958f 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -56,6 +56,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testParseIndexPath); CPPUNIT_TEST(testCreateIndexPathMap); CPPUNIT_TEST(testGenerateRandomData); + CPPUNIT_TEST(testFromHex); CPPUNIT_TEST_SUITE_END(); private: @@ -100,6 +101,7 @@ public: void testParseIndexPath(); void testCreateIndexPathMap(); void testGenerateRandomData(); + void testFromHex(); }; @@ -800,4 +802,23 @@ void UtilTest::testGenerateRandomData() CPPUNIT_ASSERT(memcmp(data1, data2, sizeof(data1)) != 0); } +void UtilTest::testFromHex() +{ + std::string src; + std::string dest; + + src = "0011fF"; + dest = util::fromHex(src); + CPPUNIT_ASSERT_EQUAL((size_t)3, dest.size()); + CPPUNIT_ASSERT_EQUAL((char)0x00, dest[0]); + CPPUNIT_ASSERT_EQUAL((char)0x11, dest[1]); + CPPUNIT_ASSERT_EQUAL((char)0xff, dest[2]); + + src = "0011f"; + CPPUNIT_ASSERT(util::fromHex(src).empty()); + + src = "001g"; + CPPUNIT_ASSERT(util::fromHex(src).empty()); +} + } // namespace aria2