Mercurial > hg > svcore
comparison data/fileio/CSVStreamWriter.h @ 1453:4b496a258782
Merge from branch streaming-csv-writer
author | Chris Cannam |
---|---|
date | Tue, 17 Apr 2018 10:52:06 +0100 |
parents | 6e9615bde1f9 |
children | 743c38b209d0 |
comparison
equal
deleted
inserted
replaced
1429:48e9f538e6e9 | 1453:4b496a258782 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2017 Queen Mary, University of London. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #ifndef SV_CSV_STREAM_WRITER_H | |
17 #define SV_CSV_STREAM_WRITER_H | |
18 | |
19 #include "base/BaseTypes.h" | |
20 #include "base/Selection.h" | |
21 #include "base/ProgressReporter.h" | |
22 #include "base/DataExportOptions.h" | |
23 #include "data/model/Model.h" | |
24 #include <QString> | |
25 #include <algorithm> | |
26 #include <numeric> | |
27 | |
28 namespace CSVStreamWriter | |
29 { | |
30 | |
31 template <class OutStream> | |
32 bool | |
33 writeInChunks(OutStream& oss, | |
34 const Model& model, | |
35 const MultiSelection& regions, | |
36 ProgressReporter* reporter = nullptr, | |
37 QString delimiter = ",", | |
38 DataExportOptions options = DataExportDefaults, | |
39 const sv_frame_t blockSize = 16384) | |
40 { | |
41 const auto selections = regions.getSelections(); | |
42 if (blockSize <= 0 || selections.empty()) return false; | |
43 | |
44 // TODO, some form of checking validity of selections? | |
45 const auto nFramesToWrite = std::accumulate( | |
46 selections.begin(), | |
47 selections.end(), | |
48 0, | |
49 [](sv_frame_t acc, const Selection& current) -> sv_frame_t { | |
50 return acc + (current.getEndFrame() - current.getStartFrame()); | |
51 } | |
52 ); | |
53 const auto finalFrameOfLastRegion = (*selections.crbegin()).getEndFrame(); | |
54 | |
55 const auto wasCancelled = [&reporter]() { | |
56 return reporter && reporter->wasCancelled(); | |
57 }; | |
58 | |
59 sv_frame_t nFramesWritten = 0; | |
60 int previousProgress = 0; | |
61 | |
62 for (const auto& extents : selections) { | |
63 const auto startFrame = extents.getStartFrame(); | |
64 const auto endFrame = extents.getEndFrame(); | |
65 auto readPtr = startFrame; | |
66 while (readPtr < endFrame) { | |
67 if (wasCancelled()) return false; | |
68 | |
69 const auto start = readPtr; | |
70 const auto end = std::min(start + blockSize, endFrame); | |
71 const auto data = model.toDelimitedDataStringSubsetWithOptions( | |
72 delimiter, | |
73 options, | |
74 start, | |
75 end | |
76 ).trimmed(); | |
77 | |
78 if ( data != "" ) { | |
79 oss << data << (end < finalFrameOfLastRegion ? "\n" : ""); | |
80 } | |
81 | |
82 nFramesWritten += end - start; | |
83 const auto currentProgress = 100 * nFramesWritten / nFramesToWrite; | |
84 const bool hasIncreased = currentProgress > previousProgress; | |
85 if (hasIncreased) { | |
86 if (reporter) reporter->setProgress(currentProgress); | |
87 previousProgress = currentProgress; | |
88 } | |
89 readPtr = end; | |
90 } | |
91 } | |
92 return !wasCancelled(); // setProgress could process event loop | |
93 } | |
94 | |
95 template <class OutStream> | |
96 bool | |
97 writeInChunks(OutStream& oss, | |
98 const Model& model, | |
99 const Selection& extents, | |
100 ProgressReporter* reporter = nullptr, | |
101 QString delimiter = ",", | |
102 DataExportOptions options = DataExportDefaults, | |
103 const sv_frame_t blockSize = 16384) | |
104 { | |
105 const auto startFrame = extents.isEmpty() ? | |
106 model.getStartFrame() : extents.getStartFrame(); | |
107 const auto endFrame = extents.isEmpty() ? | |
108 model.getEndFrame() : extents.getEndFrame(); | |
109 const auto hasValidExtents = startFrame >= 0 && endFrame > startFrame; | |
110 if (!hasValidExtents) return false; | |
111 Selection all { | |
112 startFrame, | |
113 endFrame | |
114 }; | |
115 MultiSelection regions; | |
116 regions.addSelection(all); | |
117 return CSVStreamWriter::writeInChunks( | |
118 oss, | |
119 model, | |
120 regions, | |
121 reporter, | |
122 delimiter, | |
123 options, | |
124 blockSize | |
125 ); | |
126 } | |
127 | |
128 template <class OutStream> | |
129 bool | |
130 writeInChunks(OutStream& oss, | |
131 const Model& model, | |
132 ProgressReporter* reporter = nullptr, | |
133 QString delimiter = ",", | |
134 DataExportOptions options = DataExportDefaults, | |
135 const sv_frame_t blockSize = 16384) | |
136 { | |
137 const Selection empty; | |
138 return CSVStreamWriter::writeInChunks( | |
139 oss, | |
140 model, | |
141 empty, | |
142 reporter, | |
143 delimiter, | |
144 options, | |
145 blockSize | |
146 ); | |
147 } | |
148 } // namespace CSVStreamWriter | |
149 #endif |