• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 18008514883

25 Sep 2025 01:08PM UTC coverage: 68.869% (-0.05%) from 68.919%
18008514883

push

github

paulmthompson
dlc loader for csv files

92 of 102 new or added lines in 3 files covered. (90.2%)

680 existing lines in 10 files now uncovered.

41941 of 60900 relevant lines covered (68.87%)

1139.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.45
/src/DataManager/utils/TableView/adapters/DataManagerExtension.cpp
1
#include "DataManagerExtension.h"
2

3
#include "DataManager.hpp"
4
#include "utils/TableView/adapters/AnalogDataAdapter.h"
5
#include "utils/TableView/adapters/DigitalEventDataAdapter.h"
6
#include "utils/TableView/adapters/DigitalIntervalDataAdapter.h"
7
#include "utils/TableView/adapters/LineDataAdapter.h"
8
#include "utils/TableView/adapters/PointDataAdapter.h"
9
#include "utils/TableView/interfaces/IAnalogSource.h"
10
#include "utils/TableView/interfaces/IEventSource.h"
11
#include "utils/TableView/interfaces/IIntervalSource.h"
12
#include "utils/TableView/interfaces/ILineSource.h"
13
#include "utils/TableView/interfaces/IPointSource.h"
14

15

16
#include <iostream>
17

18
// Define the static regex
19
std::regex const DataManagerExtension::s_virtualSourceRegex(R"(^(\w+)\.(x|y)$)");
20

21
DataManagerExtension::DataManagerExtension(DataManager & dataManager)
410✔
22
    : m_dataManager(dataManager) {
410✔
23
}
410✔
24

25
std::shared_ptr<IAnalogSource> DataManagerExtension::getAnalogSource(std::string const & name) {
363✔
26
    // Check cache first
27
    auto cacheIt = m_dataSourceCache.find(name);
363✔
28
    if (cacheIt != m_dataSourceCache.end()) {
363✔
29
        return cacheIt->second;
211✔
30
    }
31

32
    std::shared_ptr<IAnalogSource> source = nullptr;
152✔
33

34
    // Try to parse as virtual source first (e.g., "MyPoints.x")
35
    auto [pointDataName, component] = parseVirtualSourceName(name);
152✔
36
    if (!pointDataName.empty()) {
152✔
37
        source = createPointComponentAdapter(pointDataName, component);
16✔
38
    } else {
39
        // Try as physical analog data
40
        source = createAnalogDataAdapter(name);
136✔
41
    }
42

43
    // Cache the result (even if nullptr) to avoid repeated lookups
44
    m_dataSourceCache[name] = source;
152✔
45
    return source;
152✔
46
}
152✔
47

48
void DataManagerExtension::clearCache() {
×
49
    m_dataSourceCache.clear();
×
50
    m_eventSourceCache.clear();
×
51
    m_intervalSourceCache.clear();
×
52
    m_lineSourceCache.clear();
×
53
    m_pointSourceCache.clear();
×
54
}
×
55

56
std::shared_ptr<IAnalogSource> DataManagerExtension::createAnalogDataAdapter(std::string const & name) {
136✔
57
    try {
58
        auto analogData = m_dataManager.getData<AnalogTimeSeries>(name);
136✔
59
        if (!analogData) {
72✔
60
            return nullptr;
3✔
61
        }
62

63
        auto timeFrame_key = m_dataManager.getTimeKey(name);
69✔
64
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
69✔
65

66
        return std::make_shared<AnalogDataAdapter>(analogData, timeFrame, name);
69✔
67
    } catch (std::exception const & e) {
136✔
68
        std::cerr << "Error creating AnalogDataAdapter for '" << name << "': " << e.what() << std::endl;
64✔
69
        return nullptr;
64✔
70
    }
64✔
71
}
72

73
std::shared_ptr<IEventSource> DataManagerExtension::createDigitalEventDataAdapter(std::string const & name) {
101✔
74
    try {
75
        auto digitalEventSeries = m_dataManager.getData<DigitalEventSeries>(name);
101✔
76
        if (!digitalEventSeries) {
63✔
77
            return nullptr;
6✔
78
        }
79

80
        auto timeFrame_key = m_dataManager.getTimeKey(name);
57✔
81
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
57✔
82

83
        return std::make_shared<DigitalEventDataAdapter>(digitalEventSeries, timeFrame, name);
57✔
84
    } catch (std::exception const & e) {
101✔
85
        std::cerr << "Error creating DigitalEventDataAdapter for '" << name << "': " << e.what() << std::endl;
38✔
86
        return nullptr;
38✔
87
    }
38✔
88
}
89

90
std::shared_ptr<IIntervalSource> DataManagerExtension::createDigitalIntervalDataAdapter(std::string const & name) {
130✔
91
    try {
92
        auto digitalIntervalSeries = m_dataManager.getData<DigitalIntervalSeries>(name);
130✔
93
        if (!digitalIntervalSeries) {
83✔
94
            return nullptr;
2✔
95
        }
96

97
        auto timeFrame_key = m_dataManager.getTimeKey(name);
81✔
98
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
81✔
99

100
        return std::make_shared<DigitalIntervalDataAdapter>(digitalIntervalSeries, timeFrame, name);
81✔
101
    } catch (std::exception const & e) {
130✔
102
        std::cerr << "Error creating DigitalIntervalDataAdapter for '" << name << "': " << e.what() << std::endl;
47✔
103
        return nullptr;
47✔
104
    }
47✔
105
}
106

107
std::shared_ptr<ILineSource> DataManagerExtension::createLineDataAdapter(std::string const & name) {
1,578✔
108
    try {
109
        auto lineData = m_dataManager.getData<LineData>(name);
1,578✔
110
        if (!lineData) {
83✔
111
            return nullptr;
56✔
112
        }
113

114
        auto timeFrame_key = m_dataManager.getTimeKey(name);
27✔
115
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
27✔
116

117
        return std::make_shared<LineDataAdapter>(lineData, timeFrame, name);
27✔
118
    } catch (std::exception const & e) {
1,578✔
119
        std::cerr << "Error creating LineDataAdapter for '" << name << "': " << e.what() << std::endl;
1,495✔
120
        return nullptr;
1,495✔
121
    }
1,495✔
122
}
123

124
std::shared_ptr<IPointSource> DataManagerExtension::createPointDataAdapter(std::string const & name) {
428✔
125
    try {
126
        auto pointData = m_dataManager.getData<PointData>(name);
428✔
127
        if (!pointData) {
37✔
128
            return nullptr;
35✔
129
        }
130

131
        auto timeFrame_key = m_dataManager.getTimeKey(name);
2✔
132
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
2✔
133

134
        return std::make_shared<PointDataAdapter>(pointData, timeFrame, name);
2✔
135
    } catch (std::exception const & e) {
428✔
136
        std::cerr << "Error creating PointDataAdapter for '" << name << "': " << e.what() << std::endl;
391✔
137
        return nullptr;
391✔
138
    }
391✔
139
}
140

141

142
std::shared_ptr<IAnalogSource> DataManagerExtension::createPointComponentAdapter(
16✔
143
        std::string const & pointDataName,
144
        PointComponentAdapter::Component component) {
145

146
    try {
147
        auto pointData = m_dataManager.getData<PointData>(pointDataName);
16✔
148
        if (!pointData) {
16✔
149
            return nullptr;
1✔
150
        }
151

152
        // Check if PointData has multiple samples per timestamp
153
        // PointComponentAdapter can only handle single-sample data
154
        auto pointAdapter = std::make_shared<PointDataAdapter>(pointData, nullptr, pointDataName);
15✔
155
        if (pointAdapter->hasMultiSamples()) {
15✔
156
            std::cerr << "Cannot create PointComponentAdapter for '" << pointDataName 
157
                      << "': PointData has multiple samples per timestamp. "
158
                      << "Use PointDataAdapter with IPointSource interface instead." << std::endl;
2✔
159
            return nullptr;
2✔
160
        }
161

162
        auto timeFrame_key = m_dataManager.getTimeKey(pointDataName);
13✔
163
        auto timeFrame = m_dataManager.getTime(timeFrame_key);
13✔
164

165
        // Create the full name for the virtual source
166
        std::string fullName = pointDataName + (component == PointComponentAdapter::Component::X ? ".x" : ".y");
13✔
167

168
        return std::make_shared<PointComponentAdapter>(pointData, component, timeFrame, fullName);
13✔
169
    } catch (std::exception const & e) {
16✔
170
        std::cerr << "Error creating PointComponentAdapter for '" << pointDataName
171
                  << "' component: " << e.what() << std::endl;
×
172
        return nullptr;
×
173
    }
×
174
}
175

176
std::pair<std::string, PointComponentAdapter::Component>
177
DataManagerExtension::parseVirtualSourceName(std::string const & name) {
152✔
178
    std::smatch match;
152✔
179
    if (!std::regex_match(name, match, s_virtualSourceRegex)) {
152✔
180
        return {"", PointComponentAdapter::Component::X};// Invalid format
272✔
181
    }
182

183
    std::string dataName = match[1].str();
16✔
184
    std::string componentStr = match[2].str();
16✔
185

186
    PointComponentAdapter::Component component = (componentStr == "x") ? PointComponentAdapter::Component::X : PointComponentAdapter::Component::Y;
16✔
187

188
    return {dataName, component};
16✔
189
}
152✔
190

191
std::shared_ptr<IEventSource> DataManagerExtension::getEventSource(std::string const & name) {
318✔
192
    // Check cache first
193
    auto it = m_eventSourceCache.find(name);
318✔
194
    if (it != m_eventSourceCache.end()) {
318✔
195
        return it->second;
217✔
196
    }
197

198
    // Create a new event source adapter
199
    auto eventSource = createDigitalEventDataAdapter(name);
101✔
200
    if (eventSource) {
101✔
201
        m_eventSourceCache[name] = eventSource;
57✔
202
    } else {
203
        std::cerr << "Event source '" << name << "' not found." << std::endl;
44✔
204
    }
205
    return eventSource;
101✔
206
}
101✔
207

208
std::shared_ptr<IIntervalSource> DataManagerExtension::getIntervalSource(std::string const & name) {
243✔
209
    // Check cache first
210
    auto it = m_intervalSourceCache.find(name);
243✔
211
    if (it != m_intervalSourceCache.end()) {
243✔
212
        return it->second;
113✔
213
    }
214

215
    // Create a new interval source adapter
216
    auto intervalSource = createDigitalIntervalDataAdapter(name);
130✔
217
    if (intervalSource) {
130✔
218
        m_intervalSourceCache[name] = intervalSource;
81✔
219
    } else {
220
        std::cerr << "Interval source '" << name << "' not found." << std::endl;
49✔
221
    }
222
    return intervalSource;
130✔
223
}
130✔
224

225
std::shared_ptr<ILineSource> DataManagerExtension::getLineSource(std::string const & name) {
1,898✔
226
    // Check cache first
227
    auto it = m_lineSourceCache.find(name);
1,898✔
228
    if (it != m_lineSourceCache.end()) {
1,898✔
229
        return it->second;
320✔
230
    }
231

232
    // Create a new line source adapter
233
    auto lineSource = createLineDataAdapter(name);
1,578✔
234
    if (lineSource) {
1,578✔
235
        m_lineSourceCache[name] = lineSource;
27✔
236
    } else {
237
        std::cerr << "Line source '" << name << "' not found." << std::endl;
1,551✔
238
    }
239
    return lineSource;
1,578✔
240
}
1,578✔
241

242
std::shared_ptr<IPointSource> DataManagerExtension::getPointSource(std::string const & name) {
428✔
243
    // Check cache first
244
    auto it = m_pointSourceCache.find(name);
428✔
245
    if (it != m_pointSourceCache.end()) {
428✔
246
        return it->second;
×
247
    }
248

249
    // Create a new point source adapter
250
    auto pointSource = createPointDataAdapter(name);
428✔
251
    if (pointSource) {
428✔
252
        m_pointSourceCache[name] = pointSource;
2✔
253
    } else {
254
        std::cerr << "Point source '" << name << "' not found." << std::endl;
426✔
255
    }
256
    return pointSource;
428✔
257
}
428✔
258

259
std::optional<DataManagerExtension::SourceHandle> DataManagerExtension::resolveSource(std::string const & name) {
121✔
260
    // Try cached adapters in the typical order of usage
261
    if (auto a = getAnalogSource(name)) {
121✔
262
        return a;
48✔
263
    }
121✔
264
    if (auto i = getIntervalSource(name)) {
73✔
265
        return i;
30✔
266
    }
73✔
267
    if (auto e = getEventSource(name)) {
43✔
268
        return e;
24✔
269
    }
43✔
270
    if (auto l = getLineSource(name)) {
19✔
271
        return l;
18✔
272
    }
19✔
273
    if (auto p = getPointSource(name)) {
1✔
UNCOV
274
        return p;
×
275
    }
1✔
276
    return std::nullopt;
1✔
277
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc