From: Marcin Siodelski Date: Fri, 30 Jan 2015 10:44:22 +0000 (+0100) Subject: [3669] It is now possible to reopen a CSV file and seek to its end. X-Git-Tag: trac3712_base~13^2~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=550f8901c0ccdd53f662b6594ba65fe2e7f4d14d;p=thirdparty%2Fkea.git [3669] It is now possible to reopen a CSV file and seek to its end. --- diff --git a/src/lib/util/csv_file.cc b/src/lib/util/csv_file.cc index 5df7816977..c3c2bb9dee 100644 --- a/src/lib/util/csv_file.cc +++ b/src/lib/util/csv_file.cc @@ -261,7 +261,7 @@ CSVFile::next(CSVRow& row, const bool skip_validation) { } void -CSVFile::open() { +CSVFile::open(const bool seek_to_end) { // If file doesn't exist or is empty, we have to create our own file. if (size() == static_cast(0)) { recreate(); @@ -308,6 +308,19 @@ CSVFile::open() { addColumnInternal(header.readAt(i)); } } + + // If caller requested that the pointer is set at the end of file, + // move both read and write pointer. + if (seek_to_end) { + fs_->seekp(0, std::ios_base::end); + fs_->seekg(0, std::ios_base::end); + if (!fs_->good()) { + isc_throw(CSVFileError, "unable to move to the end of" + " CSV file '" << filename_ << "'"); + } + fs_->clear(); + } + } catch (const std::exception& ex) { close(); throw; diff --git a/src/lib/util/csv_file.h b/src/lib/util/csv_file.h index 4f12ec34c7..3296349d84 100644 --- a/src/lib/util/csv_file.h +++ b/src/lib/util/csv_file.h @@ -385,12 +385,17 @@ public: /// greater than 0. If the file doesn't exist or has size of 0, the /// file is recreated. If the existing file has been opened, the header /// is parsed and column names are initialized in the @c CSVFile object. - /// The data pointer in the file is set to the beginning of the first - /// row. In order to retrieve the row contents the @c next function should - /// be called. + /// By default, the data pointer in the file is set to the beginning of + /// the first row. In order to retrieve the row contents the @c next + /// function should be called. If a @c seek_to_end parameter is set to + /// true, the file will be opened and the interal pointer will be set + /// to the end of file. + /// + /// @param seek_to_end A boolean value which indicates if the intput and + /// output file pointer should be set at the end of file. /// /// @throw CSVFileError when IO operation fails. - void open(); + void open(const bool seek_to_end = false); /// @brief Creates a new CSV file. /// diff --git a/src/lib/util/tests/csv_file_unittest.cc b/src/lib/util/tests/csv_file_unittest.cc index 234a826e20..f3c7ba7516 100644 --- a/src/lib/util/tests/csv_file_unittest.cc +++ b/src/lib/util/tests/csv_file_unittest.cc @@ -303,6 +303,30 @@ TEST_F(CSVFileTest, openReadAllWrite) { // Any attempt to read from the file or write to it should now fail. EXPECT_FALSE(csv->next(row)); EXPECT_THROW(csv->append(row_write), CSVFileError); + + CSVRow row_write2(3); + row_write2.writeAt(0, "bird"); + row_write2.writeAt(1, 3); + row_write2.writeAt(2, "purple"); + + // Reopen the file, seek to the end of file so as we can append + // some more data. + ASSERT_NO_THROW(csv->open(true)); + // The file pointer should be at the end of file, so an attempt + // to read should result in an empty row. + ASSERT_TRUE(csv->next(row)); + EXPECT_EQ(CSVFile::EMPTY_ROW(), row); + // We should be able to append new data. + ASSERT_NO_THROW(csv->append(row_write2)); + ASSERT_NO_THROW(csv->flush()); + csv->close(); + // Check that new data has been appended. + EXPECT_EQ("animal,age,color\n" + "cat,10,white\n" + "lion,15,yellow\n" + "dog,2,blue\n" + "bird,3,purple\n", + readFile()); } // This test checks that contents may be appended to a file which hasn't