Mercurial > hg > svcore
comparison data/fileio/CSVStreamWriter.h @ 1527:710e6250a401 zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:14 +0100 |
parents | 743c38b209d0 |
children | 560453546749 |
comparison
equal
deleted
inserted
replaced
1324:d4a28d1479a8 | 1527:710e6250a401 |
---|---|
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 int currentProgress = | |
84 int(100 * nFramesWritten / nFramesToWrite); | |
85 const bool hasIncreased = currentProgress > previousProgress; | |
86 if (hasIncreased) { | |
87 if (reporter) reporter->setProgress(currentProgress); | |
88 previousProgress = currentProgress; | |
89 } | |
90 readPtr = end; | |
91 } | |
92 } | |
93 return !wasCancelled(); // setProgress could process event loop | |
94 } | |
95 | |
96 template <class OutStream> | |
97 bool | |
98 writeInChunks(OutStream& oss, | |
99 const Model& model, | |
100 const Selection& extents, | |
101 ProgressReporter* reporter = nullptr, | |
102 QString delimiter = ",", | |
103 DataExportOptions options = DataExportDefaults, | |
104 const sv_frame_t blockSize = 16384) | |
105 { | |
106 const auto startFrame = extents.isEmpty() ? | |
107 model.getStartFrame() : extents.getStartFrame(); | |
108 const auto endFrame = extents.isEmpty() ? | |
109 model.getEndFrame() : extents.getEndFrame(); | |
110 const auto hasValidExtents = startFrame >= 0 && endFrame > startFrame; | |
111 if (!hasValidExtents) return false; | |
112 Selection all { | |
113 startFrame, | |
114 endFrame | |
115 }; | |
116 MultiSelection regions; | |
117 regions.addSelection(all); | |
118 return CSVStreamWriter::writeInChunks( | |
119 oss, | |
120 model, | |
121 regions, | |
122 reporter, | |
123 delimiter, | |
124 options, | |
125 blockSize | |
126 ); | |
127 } | |
128 | |
129 template <class OutStream> | |
130 bool | |
131 writeInChunks(OutStream& oss, | |
132 const Model& model, | |
133 ProgressReporter* reporter = nullptr, | |
134 QString delimiter = ",", | |
135 DataExportOptions options = DataExportDefaults, | |
136 const sv_frame_t blockSize = 16384) | |
137 { | |
138 const Selection empty; | |
139 return CSVStreamWriter::writeInChunks( | |
140 oss, | |
141 model, | |
142 empty, | |
143 reporter, | |
144 delimiter, | |
145 options, | |
146 blockSize | |
147 ); | |
148 } | |
149 } // namespace CSVStreamWriter | |
150 #endif |