/* * Copyright (C) 2008-2009 Patrick Ohly * Copyright (C) 2009 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include SE_BEGIN_CXX #ifdef ENABLE_UNIT_TESTS template void readlines(std::istream &in, IT out) { std::string line; while (std::getline(in, line)) { *out++ = line; } } /** * implements the assignment of EnumerateChunks */ template class EnumerateChunksProxy { public: EnumerateChunksProxy(const std::string &keyword, const IT &out, const C count) : m_keyword(keyword), m_out(out), m_count(count) {} EnumerateChunksProxy &operator=(const std::string &rhs) { if (!rhs.compare(0, m_keyword.size(), m_keyword)) { m_count++; } m_out = std::make_pair(rhs, m_count); return *this; } protected: std::string m_keyword; IT m_out; C m_count; }; /** * Output iterator which identifies related chunks * by incrementing a running count each time a certain * keyword is found at the beginning of the line. * Writes the line,count pair to another output * iterator. */ template class EnumerateChunks : private EnumerateChunksProxy { public: EnumerateChunks(const std::string &keyword, const IT &out, const C count) : EnumerateChunksProxy(keyword, out, count) {} EnumerateChunksProxy &operator*() { return *this; } EnumerateChunks &operator++() { this->m_out++; return *this; } EnumerateChunks &operator++(int) { ++this->m_out; return *this; } }; template class EnumerateChunks make_enumerate_chunks(const std::string &keyword, IT out, C count) { return EnumerateChunks(keyword, out, count); } class LCSTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(LCSTest); CPPUNIT_TEST(lcs); CPPUNIT_TEST_SUITE_END(); public: void lcs() { std::ifstream file1("testcases/lcs/file1.txt"); std::ifstream file2("testcases/lcs/file2.txt"); typedef std::vector< std::pair > content; content content1, content2; readlines(file1, make_enumerate_chunks("begin", std::back_inserter(content1), 0)); readlines(file2, make_enumerate_chunks("begin", std::back_inserter(content2), 0)); std::vector< LCS::Entry > result; LCS::lcs(content1, content2, std::back_inserter(result), LCS::accessor()); std::ostringstream out; std::copy(result.begin(), result.end(), std::ostream_iterator< LCS::Entry >(out)); CPPUNIT_ASSERT_EQUAL(std::string("1, 4: begin\n" "2, 5: item1\n" "3, 6: end\n"), out.str()); CPPUNIT_ASSERT_EQUAL((size_t)3, result.size()); } }; SYNCEVOLUTION_TEST_SUITE_REGISTRATION(LCSTest); #ifdef MAIN int main(int argc, char **argv) { if (argc != 3) { std::cerr << "Usage: lcs file1 file2" << std::endl; return 1; } std::ifstream file1(argv[1]); std::ifstream file2(argv[2]); typedef std::vector< std::pair > content; content content1, content2; readlines(file1, make_enumerate_chunks("begin", std::back_inserter(content1), 0)); readlines(file2, make_enumerate_chunks("begin", std::back_inserter(content2), 0)); std::vector< LCS::Entry > result; LCS::lcs(content1, content2, std::back_inserter(result), LCS::accessor()); std::copy(result.begin(), result.end(), std::ostream_iterator< LCS::Entry >(std::cout)); std::cout << "Length: " << result.size() << std::endl; return 0; } #endif // MAIN #endif // ENABLE_UNIT_TESTS SE_END_CXX