diff data/fileio/CSVStreamWriter.h @ 1434:0684c6698e3f streaming-csv-writer

Added utility function for splitting a model selection into chunks and writing to a stream.
author Lucas Thompson <dev@lucas.im>
date Tue, 17 Apr 2018 10:03:49 +0100
parents b5283878cca2
children 09c2ba31a711
line wrap: on
line diff
--- a/data/fileio/CSVStreamWriter.h	Tue Apr 17 10:03:49 2018 +0100
+++ b/data/fileio/CSVStreamWriter.h	Tue Apr 17 10:03:49 2018 +0100
@@ -16,11 +16,85 @@
 #ifndef _CSV_STREAM_WRITER_H_
 #define _CSV_STREAM_WRITER_H_
 
-class CSVStreamWriter
+#include "base/BaseTypes.h"
+#include "base/Selection.h"
+#include "base/ProgressReporter.h"
+#include "base/DataExportOptions.h"
+#include "data/model/Model.h"
+#include <QString>
+#include <algorithm>
+
+namespace CSV
 {
+using Completed = bool;
 
-};
+template <class OutStream>
+auto writeToStreamInChunks(
+    OutStream& oss,
+    const Model& model,
+    const Selection& extents,
+    ProgressReporter* reporter = nullptr,
+    QString delimiter = ",",
+    DataExportOptions options = DataExportDefaults,
+    const sv_frame_t blockSize = 16384
+) -> Completed
+{
+    if (blockSize <= 0) return false;
+    sv_frame_t readPtr = extents.isEmpty() ?
+        model.getStartFrame() : extents.getStartFrame();
+    sv_frame_t endFrame = extents.isEmpty() ?
+        model.getEndFrame() : extents.getEndFrame();
+    int previousPercentagePoint = 0;
 
-#endif
+    const auto wasCancelled = [&reporter]() { 
+        return reporter && reporter->wasCancelled(); 
+    };
 
-    
+    while (readPtr < endFrame) {
+        if (wasCancelled()) return false;
+
+        const auto start = readPtr;
+        const auto end = std::min(start + blockSize, endFrame);
+
+        oss << model.toDelimitedDataStringSubsetWithOptions(
+            delimiter,
+            options,
+            start,
+            end
+        ) << (end < endFrame ? "\n" : "");
+
+        const auto currentPercentage = 100 * end / endFrame;
+        const bool hasIncreased = currentPercentage > previousPercentagePoint;
+
+        if (hasIncreased) {
+            if (reporter) reporter->setProgress(currentPercentage);
+            previousPercentagePoint = currentPercentage;
+        }
+        readPtr = end;
+    }
+    return !wasCancelled(); // setProgress could process event loop
+}
+
+template <class OutStream>
+auto writeToStreamInChunks(
+    OutStream& oss,
+    const Model& model,
+    ProgressReporter* reporter = nullptr,
+    QString delimiter = ",",
+    DataExportOptions options = DataExportDefaults,
+    const sv_frame_t blockSize = 16384
+) -> Completed
+{
+    const Selection empty;
+    return CSV::writeToStreamInChunks(
+        oss,
+        model,
+        empty,
+        reporter,
+        delimiter,
+        options,
+        blockSize
+    );
+}
+} // namespace
+#endif
\ No newline at end of file