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

paulmthompson / WhiskerToolbox / 17700769195

13 Sep 2025 06:37PM UTC coverage: 71.744% (-0.1%) from 71.842%
17700769195

push

github

paulmthompson
update to new version of whisker tracker

7 of 84 new or added lines in 2 files covered. (8.33%)

112 existing lines in 5 files now uncovered.

37096 of 51706 relevant lines covered (71.74%)

1307.13 hits per line

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

81.38
/src/DataManager/utils/TableView/ComputerRegistry.hpp
1
#ifndef COMPUTER_REGISTRY_HPP
2
#define COMPUTER_REGISTRY_HPP
3

4
#include "utils/TableView/ComputerRegistryTypes.hpp"
5
#include "utils/TableView/interfaces/IColumnComputer.h"
6
#include "utils/TableView/interfaces/IMultiColumnComputer.h"
7
#include "utils/TableView/interfaces/IRowSelector.h"
8

9
#include <deque>
10
#include <functional>
11
#include <map>
12
#include <memory>
13
#include <optional>
14
#include <string>
15
#include <typeindex>
16
#include <variant>
17
#include <vector>
18

19
class TimeFrame;
20

21
/**
22
 * @brief Abstract base for parameter descriptors that provide UI hints without Qt dependencies.
23
 */
24
class IParameterDescriptor {
25
public:
26
    IParameterDescriptor();
27
    virtual ~IParameterDescriptor();
28
    virtual std::string getName() const = 0;
29
    virtual std::string getDescription() const = 0;
30
    virtual bool isRequired() const = 0;
31
    virtual std::string getUIHint() const = 0;// "enum", "text", "number", etc.
32
    virtual std::map<std::string, std::string> getUIProperties() const = 0;
33
    virtual std::unique_ptr<IParameterDescriptor> clone() const = 0;
34
};
35

36
/**
37
 * @brief Parameter descriptor for enumerated/choice parameters.
38
 */
39
class EnumParameterDescriptor : public IParameterDescriptor {
40
    std::string name_;
41
    std::string description_;
42
    std::vector<std::string> options_;
43
    std::string defaultValue_;
44
    bool required_;
45

46
public:
47
    EnumParameterDescriptor(std::string name, std::string description,
1,024✔
48
                            std::vector<std::string> options, std::string defaultValue = "",
49
                            bool required = true)
50
        : name_(std::move(name)),
1,024✔
51
          description_(std::move(description)),
1,024✔
52
          options_(std::move(options)),
1,024✔
53
          defaultValue_(std::move(defaultValue)),
1,024✔
54
          required_(required) {}
1,024✔
55

56
    std::string getName() const override { return name_; }
×
57
    std::string getDescription() const override { return description_; }
×
UNCOV
58
    bool isRequired() const override { return required_; }
×
59
    std::string getUIHint() const override { return "enum"; }
×
60

UNCOV
61
    std::map<std::string, std::string> getUIProperties() const override {
×
UNCOV
62
        std::map<std::string, std::string> props;
×
63

64
        // Join options with comma
65
        std::string optionsStr;
×
66
        for (size_t i = 0; i < options_.size(); ++i) {
×
UNCOV
67
            if (i > 0) optionsStr += ",";
×
UNCOV
68
            optionsStr += options_[i];
×
69
        }
70

71
        props["options"] = optionsStr;
×
72
        props["default"] = defaultValue_;
×
UNCOV
73
        return props;
×
UNCOV
74
    }
×
75

76
    std::unique_ptr<IParameterDescriptor> clone() const override {
734✔
77
        return std::make_unique<EnumParameterDescriptor>(name_, description_, options_, defaultValue_, required_);
734✔
78
    }
79

80
    std::vector<std::string> const & getOptions() const { return options_; }
81
    std::string const & getDefaultValue() const { return defaultValue_; }
82
};
83

84
/**
85
 * @brief Parameter descriptor for integer numeric parameters.
86
 */
87
class IntParameterDescriptor : public IParameterDescriptor {
88
    std::string name_;
89
    std::string description_;
90
    int defaultValue_;
91
    int minValue_;
92
    int maxValue_;
93
    bool required_;
94

95
public:
96
    IntParameterDescriptor(std::string name, std::string description,
871✔
97
                           int defaultValue = 0, int minValue = 0, int maxValue = 1000000,
98
                           bool required = true)
99
        : name_(std::move(name)),
871✔
100
          description_(std::move(description)),
871✔
101
          defaultValue_(defaultValue),
871✔
102
          minValue_(minValue),
871✔
103
          maxValue_(maxValue),
871✔
104
          required_(required) {}
871✔
105

106
    std::string getName() const override { return name_; }
1✔
107
    std::string getDescription() const override { return description_; }
×
108
    bool isRequired() const override { return required_; }
×
109
    std::string getUIHint() const override { return "number"; }
3✔
110

111
    std::map<std::string, std::string> getUIProperties() const override {
×
112
        return {
UNCOV
113
                {"default", std::to_string(defaultValue_)},
×
UNCOV
114
                {"min", std::to_string(minValue_)},
×
UNCOV
115
                {"max", std::to_string(maxValue_)}};
×
UNCOV
116
    }
×
117

118
    std::unique_ptr<IParameterDescriptor> clone() const override {
581✔
119
        return std::make_unique<IntParameterDescriptor>(name_, description_, defaultValue_, minValue_, maxValue_, required_);
581✔
120
    }
121
};
122

123
/**
124
 * @brief Non-templated base class for type-erased computer storage.
125
 * 
126
 * This allows us to store different templated IColumnComputer instances
127
 * in a single container with proper polymorphic destruction.
128
 */
129
class IComputerBase {
130
public:
131
    virtual ~IComputerBase() = default;
247✔
132

133
    // Make this class non-copyable and non-movable since it's a pure interface
134
    IComputerBase(IComputerBase const &) = delete;
135
    IComputerBase & operator=(IComputerBase const &) = delete;
136
    IComputerBase(IComputerBase &&) = delete;
137
    IComputerBase & operator=(IComputerBase &&) = delete;
138

139
protected:
140
    IComputerBase() = default;
247✔
141
};
142

143
/**
144
 * @brief Template wrapper that implements IComputerBase for specific computer types.
145
 */
146
template<typename T>
147
class ComputerWrapper : public IComputerBase {
148
public:
149
    explicit ComputerWrapper(std::unique_ptr<IColumnComputer<T>> computer)
236✔
150
        : computer_(std::move(computer)) {}
236✔
151

152
    IColumnComputer<T> * get() const { return computer_.get(); }
153

154
    /**
155
     * @brief Gets the underlying typed computer instance as a shared pointer.
156
     * @return Shared pointer to the typed computer interface.
157
     */
158
    std::shared_ptr<IColumnComputer<T>> getComputer() const {
159
        return std::shared_ptr<IColumnComputer<T>>(computer_.get(), [](IColumnComputer<T> *) {});
160
    }
161

162
    /**
163
     * @brief Transfers ownership of the underlying computer.
164
     * @return Unique pointer to the typed computer interface.
165
     */
166
    std::unique_ptr<IColumnComputer<T>> releaseComputer() {
153✔
167
        return std::move(computer_);
153✔
168
    }
169

170
private:
171
    std::unique_ptr<IColumnComputer<T>> computer_;
172
};
173

174
/**
175
 * @brief Template wrapper to type-erase IMultiColumnComputer<T> in the registry.
176
 */
177
template<typename T>
178
class MultiComputerWrapper : public IComputerBase {
179
public:
180
    explicit MultiComputerWrapper(std::unique_ptr<IMultiColumnComputer<T>> computer)
11✔
181
        : computer_(std::move(computer)) {}
11✔
182

183
    IMultiColumnComputer<T> * get() const { return computer_.get(); }
184

185
    std::shared_ptr<IMultiColumnComputer<T>> getComputer() const {
186
        return std::shared_ptr<IMultiColumnComputer<T>>(computer_.get(), [](IMultiColumnComputer<T> *) {});
187
    }
188

189
    std::unique_ptr<IMultiColumnComputer<T>> releaseComputer() {
11✔
190
        return std::move(computer_);
11✔
191
    }
192

193
private:
194
    std::unique_ptr<IMultiColumnComputer<T>> computer_;
195
};
196

197

198
/**
199
 * @brief Information about available computer parameters.
200
 */
201
struct ComputerParameterInfo {
202
    std::string name;        ///< Parameter name
203
    std::string description; ///< Human-readable description
204
    std::type_index type;    ///< Type of the parameter
205
    bool isRequired;         ///< Whether the parameter is required
206
    std::string defaultValue;///< String representation of default value (if any)
207

208
    ComputerParameterInfo();
209
    ComputerParameterInfo(std::string name_, std::string description_, std::type_index type_, bool required = false, std::string defaultValue_ = "");
210

211
    ~ComputerParameterInfo();
212
};
213

214
/**
215
 * @brief Information about an available computer.
216
 */
217
struct ComputerInfo {
218
    std::string name;                                                       ///< Display name for the computer
219
    std::string description;                                                ///< Human-readable description
220
    std::type_index outputType;                                             ///< Type of the computed output
221
    std::string outputTypeName;                                             ///< Human-readable name of the output type
222
    bool isVectorType;                                                      ///< True if output type is std::vector<T>
223
    std::type_index elementType;                                            ///< For vector types, the element type; same as outputType for non-vectors
224
    std::string elementTypeName;                                            ///< Human-readable name of the element type
225
    RowSelectorType requiredRowSelector;                                    ///< Required row selector type
226
    std::type_index requiredSourceType;                                     ///< Required data source interface type
227
    std::vector<std::unique_ptr<IParameterDescriptor>> parameterDescriptors;///< Parameter descriptors for UI generation
228
    bool isMultiOutput = false;                                             ///< True if computer produces multiple outputs of same type
229
    // Optional factory to derive output suffixes from parameters for discovery/UI
230
    std::function<std::vector<std::string>(std::map<std::string, std::string> const &)> makeOutputSuffixes;
231

232
    // Default constructor
233
    ComputerInfo()
234
        : name(),
235
          description(),
236
          outputType(typeid(void)),
237
          outputTypeName("void"),
238
          isVectorType(false),
239
          elementType(typeid(void)),
240
          elementTypeName("void"),
241
          requiredRowSelector(RowSelectorType::IntervalBased),
242
          requiredSourceType(typeid(void)),
243
          parameterDescriptors() {}
244

245
    // Helper constructor for simple types
246
    ComputerInfo(std::string name_, std::string description_, std::type_index outputType_,
4,930✔
247
                 std::string outputTypeName_, RowSelectorType rowSelector_, std::type_index sourceType_)
248
        : name(std::move(name_)),
4,930✔
249
          description(std::move(description_)),
4,930✔
250
          outputType(outputType_),
4,930✔
251
          outputTypeName(std::move(outputTypeName_)),
4,930✔
252
          isVectorType(false),
4,930✔
253
          elementType(outputType_),
4,930✔
254
          elementTypeName(outputTypeName_),
4,930✔
255
          requiredRowSelector(rowSelector_),
4,930✔
256
          requiredSourceType(sourceType_),
4,930✔
257
          parameterDescriptors() {}
4,930✔
258

259
    // Constructor with parameter descriptors for simple types
260
    ComputerInfo(std::string name_, std::string description_, std::type_index outputType_,
580✔
261
                 std::string outputTypeName_, RowSelectorType rowSelector_, std::type_index sourceType_,
262
                 std::vector<std::unique_ptr<IParameterDescriptor>> parameterDescriptors_)
263
        : name(std::move(name_)),
580✔
264
          description(std::move(description_)),
580✔
265
          outputType(outputType_),
580✔
266
          outputTypeName(std::move(outputTypeName_)),
580✔
267
          isVectorType(false),
580✔
268
          elementType(outputType_),
580✔
269
          elementTypeName(outputTypeName_),
580✔
270
          requiredRowSelector(rowSelector_),
580✔
271
          requiredSourceType(sourceType_),
580✔
272
          parameterDescriptors(std::move(parameterDescriptors_)) {}
580✔
273

274
    // Helper constructor for vector types
275
    ComputerInfo(std::string name_, std::string description_, std::type_index outputType_,
580✔
276
                 std::string outputTypeName_, std::type_index elementType_, std::string elementTypeName_,
277
                 RowSelectorType rowSelector_, std::type_index sourceType_)
278
        : name(std::move(name_)),
580✔
279
          description(std::move(description_)),
580✔
280
          outputType(outputType_),
580✔
281
          outputTypeName(std::move(outputTypeName_)),
580✔
282
          isVectorType(true),
580✔
283
          elementType(elementType_),
580✔
284
          elementTypeName(std::move(elementTypeName_)),
580✔
285
          requiredRowSelector(rowSelector_),
580✔
286
          requiredSourceType(sourceType_),
580✔
287
          parameterDescriptors() {}
580✔
288

289
    // Helper constructor for vector types with parameter descriptors
290
    ComputerInfo(std::string name_, std::string description_, std::type_index outputType_,
290✔
291
                 std::string outputTypeName_, std::type_index elementType_, std::string elementTypeName_,
292
                 RowSelectorType rowSelector_, std::type_index sourceType_,
293
                 std::vector<std::unique_ptr<IParameterDescriptor>> parameterDescriptors_)
294
        : name(std::move(name_)),
290✔
295
          description(std::move(description_)),
290✔
296
          outputType(outputType_),
290✔
297
          outputTypeName(std::move(outputTypeName_)),
290✔
298
          isVectorType(true),
290✔
299
          elementType(elementType_),
290✔
300
          elementTypeName(std::move(elementTypeName_)),
290✔
301
          requiredRowSelector(rowSelector_),
290✔
302
          requiredSourceType(sourceType_),
290✔
303
          parameterDescriptors(std::move(parameterDescriptors_)) {}
290✔
304

305
    bool hasParameters() const { return !parameterDescriptors.empty(); }
1✔
306

307
    ComputerInfo(ComputerInfo const & other)
15,055✔
308
        : name(other.name),
15,055✔
309
          description(other.description),
15,055✔
310
          outputType(other.outputType),
15,055✔
311
          outputTypeName(other.outputTypeName),
15,055✔
312
          isVectorType(other.isVectorType),
15,055✔
313
          elementType(other.elementType),
15,055✔
314
          elementTypeName(other.elementTypeName),
15,055✔
315
          requiredRowSelector(other.requiredRowSelector),
15,055✔
316
          requiredSourceType(other.requiredSourceType),
15,055✔
317
          isMultiOutput(other.isMultiOutput),
15,055✔
318
          makeOutputSuffixes(other.makeOutputSuffixes) {
15,055✔
319
        // Deep copy parameter descriptors
320
        parameterDescriptors.reserve(other.parameterDescriptors.size());
15,055✔
321
        for (auto const & param: other.parameterDescriptors) {
16,370✔
322
            parameterDescriptors.push_back(param->clone());
1,315✔
323
        }
324
    }
15,055✔
325

326
    ComputerInfo & operator=(ComputerInfo const & other) {
327
        if (this != &other) {
328
            name = other.name;
329
            description = other.description;
330
            outputType = other.outputType;
331
            outputTypeName = other.outputTypeName;
332
            isVectorType = other.isVectorType;
333
            elementType = other.elementType;
334
            elementTypeName = other.elementTypeName;
335
            requiredRowSelector = other.requiredRowSelector;
336
            requiredSourceType = other.requiredSourceType;
337
            isMultiOutput = other.isMultiOutput;
338
            makeOutputSuffixes = other.makeOutputSuffixes;
339

340
            // Deep copy parameter descriptors
341
            parameterDescriptors.clear();
342
            parameterDescriptors.reserve(other.parameterDescriptors.size());
343
            for (auto const & param: other.parameterDescriptors) {
344
                parameterDescriptors.push_back(param->clone());
345
            }
346
        }
347
        return *this;
348
    }
349
};
350

351
/**
352
 * @brief Factory function type for creating computer instances.
353
 * 
354
 * The function takes a data source variant and a map of parameter values,
355
 * and returns a type-erased computer instance.
356
 */
357
using ComputerFactory = std::function<std::unique_ptr<IComputerBase>(
358
        DataSourceVariant const & source,
359
        std::map<std::string, std::string> const & parameters)>;
360

361
using MultiComputerFactory = std::function<std::unique_ptr<IComputerBase>(
362
        DataSourceVariant const & source,
363
        std::map<std::string, std::string> const & parameters)>;
364

365
/**
366
 * @brief Information about an available adapter.
367
 */
368
struct AdapterInfo {
369
    std::string name;                             ///< Display name for the adapter
370
    std::string description;                      ///< Human-readable description
371
    std::type_index inputType;                    ///< Input data type (e.g., typeid(PointData))
372
    std::type_index outputType;                   ///< Output interface type (e.g., typeid(IAnalogSource))
373
    std::vector<ComputerParameterInfo> parameters;///< Adapter-specific parameters
374

375
    AdapterInfo()
376
        : name(),
377
          description(),
378
          inputType(typeid(void)),
379
          outputType(typeid(void)),
380
          parameters() {}
381

382
    AdapterInfo(std::string name_, std::string description_, std::type_index inputType_,
870✔
383
                std::type_index outputType_, std::vector<ComputerParameterInfo> params = {})
384
        : name(std::move(name_)),
870✔
385
          description(std::move(description_)),
870✔
386
          inputType(inputType_),
870✔
387
          outputType(outputType_),
870✔
388
          parameters(std::move(params)) {}
870✔
389
};
390

391
/**
392
 * @brief Factory function type for creating adapter instances.
393
 */
394
using AdapterFactory = std::function<DataSourceVariant(
395
        std::shared_ptr<void> const & sourceData,
396
        std::shared_ptr<TimeFrame> const & timeFrame,
397
        std::string const & name,
398
        std::map<std::string, std::string> const & parameters)>;
399

400
/**
401
 * @brief Registry for TableView column computers and data adapters.
402
 * 
403
 * This registry manages the available computers that can generate table columns
404
 * from different data source types and row selector combinations. It also
405
 * manages adapters that can convert raw data types into interface types
406
 * suitable for use with computers.
407
 */
408
class ComputerRegistry {
409
public:
410
    ComputerRegistry();
411

412
    // Make registry non-copyable and non-movable
413
    ComputerRegistry(ComputerRegistry const &) = delete;
414
    ComputerRegistry & operator=(ComputerRegistry const &) = delete;
415
    ComputerRegistry(ComputerRegistry &&) = delete;
416
    ComputerRegistry & operator=(ComputerRegistry &&) = delete;
417

418
    /**
419
     * @brief Gets available computers for a specific row selector and data source combination.
420
     * @param rowSelectorType The type of row selector being used.
421
     * @param dataSource The data source variant.
422
     * @return Vector of ComputerInfo describing available computers.
423
     */
424
    std::vector<ComputerInfo> getAvailableComputers(
425
            RowSelectorType rowSelectorType,
426
            DataSourceVariant const & dataSource) const;
427

428
    /**
429
     * @brief Gets available adapters for a specific data type.
430
     * @param dataType The type index of the raw data type.
431
     * @return Vector of AdapterInfo describing available adapters.
432
     */
433
    std::vector<AdapterInfo> getAvailableAdapters(std::type_index dataType) const;
434

435
    /**
436
     * @brief Creates a computer instance by name.
437
     * @param computerName The name of the computer to create.
438
     * @param dataSource The data source to use.
439
     * @param parameters Map of parameter name -> string value.
440
     * @return Type-erased unique_ptr to the computer instance, or nullptr if creation failed.
441
     */
442
    std::unique_ptr<IComputerBase> createComputer(
443
            std::string const & computerName,
444
            DataSourceVariant const & dataSource,
445
            std::map<std::string, std::string> const & parameters = {}) const;
446

447
    std::unique_ptr<IComputerBase> createMultiComputer(
448
            std::string const & computerName,
449
            DataSourceVariant const & dataSource,
450
            std::map<std::string, std::string> const & parameters = {}) const;
451

452
    /**
453
     * @brief Creates an adapter instance by name.
454
     * @param adapterName The name of the adapter to create.
455
     * @param sourceData The raw data to adapt.
456
     * @param timeFrame The time frame for the adapted data.
457
     * @param name The name for the adapted data source.
458
     * @param parameters Map of parameter name -> string value.
459
     * @return DataSourceVariant containing the adapted interface, or empty variant if creation failed.
460
     */
461
    DataSourceVariant createAdapter(
462
            std::string const & adapterName,
463
            std::shared_ptr<void> const & sourceData,
464
            std::shared_ptr<TimeFrame> const & timeFrame,
465
            std::string const & name,
466
            std::map<std::string, std::string> const & parameters = {}) const;
467

468
    /**
469
     * @brief Finds computer info by name.
470
     * @param computerName The name of the computer.
471
     * @return Pointer to ComputerInfo, or nullptr if not found.
472
     */
473
    ComputerInfo const * findComputerInfo(std::string const & computerName) const;
474

475
    /**
476
     * @brief Finds adapter info by name.
477
     * @param adapterName The name of the adapter.
478
     * @return Pointer to AdapterInfo, or nullptr if not found.
479
     */
480
    AdapterInfo const * findAdapterInfo(std::string const & adapterName) const;
481

482
    /**
483
     * @brief Gets all registered computer names.
484
     * @return Vector of all computer names.
485
     */
486
    std::vector<std::string> getAllComputerNames() const;
487

488
    /**
489
     * @brief Gets all registered adapter names.
490
     * @return Vector of all adapter names.
491
     */
492
    std::vector<std::string> getAllAdapterNames() const;
493

494
    // Enhanced type discovery methods
495

496
    /**
497
     * @brief Gets all available output types that computers can produce.
498
     * @return Vector of type_index values representing all possible output types.
499
     */
500
    std::vector<std::type_index> getAvailableOutputTypes() const;
501

502
    /**
503
     * @brief Gets human-readable names for available output types.
504
     * @return Map from type_index to human-readable type name.
505
     */
506
    std::map<std::type_index, std::string> getOutputTypeNames() const;
507

508
    /**
509
     * @brief Gets computers that can produce a specific output type.
510
     * @param outputType The desired output type.
511
     * @param rowSelectorType Optional filter by row selector type.
512
     * @param sourceType Optional filter by required source type.
513
     * @return Vector of ComputerInfo for computers matching the criteria.
514
     */
515
    std::vector<ComputerInfo> getComputersByOutputType(
516
            std::type_index outputType,
517
            std::optional<RowSelectorType> rowSelectorType = std::nullopt,
518
            std::optional<std::type_index> sourceType = std::nullopt) const;
519

520
    /**
521
     * @brief Checks if a computer supports vector output types.
522
     * @param computerName The name of the computer to check.
523
     * @return True if the computer outputs vector types, false otherwise.
524
     */
525
    bool isVectorComputer(std::string const & computerName) const;
526

527
    /**
528
     * @brief Gets the element type for vector-output computers.
529
     * @param computerName The name of the computer.
530
     * @return type_index of the element type, or typeid(void) if not a vector computer.
531
     */
532
    std::type_index getElementType(std::string const & computerName) const;
533

534
    /**
535
     * @brief Creates a type-safe computer with known output type.
536
     * 
537
     * This template method provides compile-time type safety when the caller
538
     * knows the expected output type. It returns a properly typed computer
539
     * interface rather than a type-erased one.
540
     * 
541
     * @tparam T The expected output type of the computer.
542
     * @param computerName The name of the computer to create.
543
     * @param dataSource The data source to use.
544
     * @param parameters Map of parameter name -> string value.
545
     * @return Unique pointer to IColumnComputer<T>, or nullptr if creation failed or type mismatch.
546
     */
547
    template<typename T>
548
    std::unique_ptr<IColumnComputer<T>> createTypedComputer(
111✔
549
            std::string const & computerName,
550
            DataSourceVariant const & dataSource,
551
            std::map<std::string, std::string> const & parameters = {}) const {
552
        auto info = findComputerInfo(computerName);
111✔
553
        if (!info || info->outputType != typeid(T)) {
111✔
UNCOV
554
            return nullptr;
×
555
        }
556

557
        auto base_computer = createComputer(computerName, dataSource, parameters);
111✔
558
        if (!base_computer) {
111✔
UNCOV
559
            return nullptr;
×
560
        }
561

562
        // Safe cast since we verified the type
563
        auto wrapper = dynamic_cast<ComputerWrapper<T> *>(base_computer.get());
111✔
564
        if (!wrapper) {
111✔
UNCOV
565
            return nullptr;
×
566
        }
567
        // Extract the underlying computer and then delete the wrapper by resetting base_computer
568
        auto typed = wrapper->releaseComputer();
111✔
569
        base_computer.reset();
111✔
570
        return typed;
111✔
571
    }
111✔
572

573
    template<typename T>
574
    std::unique_ptr<IMultiColumnComputer<T>> createTypedMultiComputer(
5✔
575
            std::string const & computerName,
576
            DataSourceVariant const & dataSource,
577
            std::map<std::string, std::string> const & parameters = {}) const {
578
        auto info = findComputerInfo(computerName);
5✔
579
        if (!info || info->outputType != typeid(T) || !info->isMultiOutput) {
5✔
UNCOV
580
            return nullptr;
×
581
        }
582

583
        auto base_computer = createMultiComputer(computerName, dataSource, parameters);
5✔
584
        if (!base_computer) {
5✔
UNCOV
585
            return nullptr;
×
586
        }
587

588
        auto wrapper = dynamic_cast<MultiComputerWrapper<T> *>(base_computer.get());
5✔
589
        if (!wrapper) {
5✔
UNCOV
590
            return nullptr;
×
591
        }
592

593
        auto typed = wrapper->releaseComputer();
5✔
594
        base_computer.reset();
5✔
595
        return typed;
5✔
596
    }
5✔
597

598
private:
599
    // Computer registration storage
600
    std::deque<ComputerInfo> all_computers_;
601
    std::map<std::string, ComputerFactory> computer_factories_;
602
    std::map<std::string, MultiComputerFactory> multi_computer_factories_;
603

604
    // Maps (RowSelectorType, SourceTypeIndex) -> vector<ComputerInfo*>
605
    std::map<std::pair<RowSelectorType, std::type_index>, std::vector<ComputerInfo const *>> selector_source_to_computers_;
606

607
    // Computer name lookup
608
    std::map<std::string, ComputerInfo const *> name_to_computer_;
609

610
    // Adapter registration storage
611
    std::deque<AdapterInfo> all_adapters_;
612
    std::map<std::string, AdapterFactory> adapter_factories_;
613

614
    // Maps input type_index -> vector<AdapterInfo*>
615
    std::map<std::type_index, std::vector<AdapterInfo const *>> input_type_to_adapters_;
616

617
    // Adapter name lookup
618
    std::map<std::string, AdapterInfo const *> name_to_adapter_;
619

620
    /**
621
     * @brief Registers a computer with the registry.
622
     * @param info ComputerInfo describing the computer.
623
     * @param factory Factory function for creating instances.
624
     */
625
    void registerComputer(ComputerInfo info, ComputerFactory factory);
626

627
    void registerMultiComputer(ComputerInfo info, MultiComputerFactory factory);
628

629
    /**
630
     * @brief Registers an adapter with the registry.
631
     * @param info AdapterInfo describing the adapter.
632
     * @param factory Factory function for creating instances.
633
     */
634
    void registerAdapter(AdapterInfo info, AdapterFactory factory);
635

636
    /**
637
     * @brief Pre-computes the mapping from (row selector, source type) to computers.
638
     */
639
    void computeComputerMappings();
640

641
    /**
642
     * @brief Pre-computes the mapping from input types to adapters.
643
     */
644
    void computeAdapterMappings();
645

646
    /**
647
     * @brief Helper function to get the type index from a DataSourceVariant.
648
     */
649
    std::type_index getSourceTypeIndex(DataSourceVariant const & source) const;
650

651
    /**
652
     * @brief Registers all built-in computers.
653
     */
654
    void registerBuiltInComputers();
655

656
    /**
657
     * @brief Registers all built-in adapters.
658
     */
659
    void registerBuiltInAdapters();
660
};
661

662
#endif// COMPUTER_REGISTRY_HPP
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