| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <stdexcept> | ||
| 4 | #include <cstdio> | ||
| 5 | #include <cstdint> | ||
| 6 | |||
| 7 | #include "na64detID/detectorIDSelect.h" | ||
| 8 | |||
| 9 | namespace na64dp { | ||
| 10 | |||
| 11 | namespace errors { | ||
| 12 | |||
| 13 | class SelectorBuildupFailure : public std::runtime_error { | ||
| 14 | private: | ||
| 15 | int _rc; | ||
| 16 | char _errBf[256]; | ||
| 17 | public: | ||
| 18 | SelectorBuildupFailure( int rc, const char * errBf ) throw(); | ||
| 19 | int compile_return_code() const throw() { return _rc; } | ||
| 20 | ✗ | virtual const char * what() const throw() { return _errBf; } | |
| 21 | }; | ||
| 22 | |||
| 23 | } | ||
| 24 | |||
| 25 | namespace dsul { | ||
| 26 | |||
| 27 | typedef na64dp_dsul_CodeVal_t CodeVal_t; | ||
| 28 | typedef na64dp_dsul_PrincipalValue_t Principal_t; | ||
| 29 | |||
| 30 | /**\brief Represents a generalized selector predicate run-time function | ||
| 31 | * | ||
| 32 | * The details on DSuL is given on :ref:`DSuL` page. This class maintains the | ||
| 33 | * lifecycle of expression being "compiled" into some kind of in-memory buffer, | ||
| 34 | * capable for reasonably fast reentrant evaluation over principal values. | ||
| 35 | * | ||
| 36 | * This template class has to be parameterised with some name resolution | ||
| 37 | * context type. Instances of this class has to be considered "valid" only | ||
| 38 | * while particular instance name-resolution context is "valid". | ||
| 39 | * */ | ||
| 40 | template< typename PrincipalT | ||
| 41 | , typename ContextT > | ||
| 42 | class Selector { | ||
| 43 | private: | ||
| 44 | /// Evaluation buffer pointer | ||
| 45 | char * _buffer; | ||
| 46 | public: | ||
| 47 | typedef na64dp_dsul_PrincipalValue_t PrincipalValue; | ||
| 48 | typedef na64dpsu_SymDefinition SymDef; | ||
| 49 | public: | ||
| 50 | /// "Compiles" selection given by string expression and list of definitions | ||
| 51 | 8 | Selector( const std::string & expr | |
| 52 | , const SymDef * getters | ||
| 53 | , const ContextT & ctx | ||
| 54 | 8 | , std::ostream * dbgStream=nullptr ) : _buffer(nullptr) { | |
| 55 | char errBf[128]; | ||
| 56 |
1/1✓ Branch 1 taken 4 times.
|
8 | std::string expr_(expr); |
| 57 | |||
| 58 | int rc; | ||
| 59 | 8 | size_t bufferSize = 512; | |
| 60 | 8 | char * dump = nullptr; | |
| 61 | 8 | size_t dumpSize = 0; | |
| 62 | do { | ||
| 63 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
10 | if( _buffer ) { |
| 64 | 2 | free(_buffer); | |
| 65 | } | ||
| 66 | 10 | FILE * dbgF = NULL; | |
| 67 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
10 | if( dbgStream ) { |
| 68 | ✗ | if( dump ) { | |
| 69 | ✗ | free(dump); | |
| 70 | ✗ | dump = NULL; | |
| 71 | ✗ | dumpSize = 0; | |
| 72 | } | ||
| 73 | ✗ | dbgF = open_memstream( &dump, &dumpSize ); | |
| 74 | } | ||
| 75 | 10 | _buffer = (char*) malloc(bufferSize); | |
| 76 |
1/1✓ Branch 2 taken 5 times.
|
10 | rc = na64dp_dsul_compile_detector_selection( const_cast<char*>(expr_.c_str()) |
| 77 | , getters | ||
| 78 | , const_cast<ContextT*>(&ctx) | ||
| 79 | , _buffer, bufferSize | ||
| 80 | , errBf, sizeof(errBf) | ||
| 81 | , dbgF ); | ||
| 82 | 10 | bufferSize *= 2; // enlarge buffer each failed attempt | |
| 83 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
10 | if( dbgF ) { |
| 84 | ✗ | fclose(dbgF); | |
| 85 | } | ||
| 86 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
10 | } while( -2 == rc ); |
| 87 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
8 | if( dbgStream ) { |
| 88 | ✗ | *dbgStream << std::string(dump, dumpSize); | |
| 89 | ✗ | free(dump); | |
| 90 | } | ||
| 91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
8 | if( 0 != rc ) { |
| 92 | ✗ | throw errors::SelectorBuildupFailure( rc, errBf ); | |
| 93 | } | ||
| 94 |
1/1✓ Branch 1 taken 4 times.
|
8 | na64dp_dsul_update_extern_symbols( _buffer, const_cast<ContextT*>(&ctx) ); |
| 95 | 8 | } | |
| 96 | /// Deletes connected evaluation buffer, if any. | ||
| 97 | 2 | ~Selector() { | |
| 98 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if(_buffer) |
| 99 | 2 | free(_buffer); | |
| 100 | 2 | } | |
| 101 | /// Updates extern definitions | ||
| 102 | ✗ | void reset_context( const ContextT & ctx ) { | |
| 103 | ✗ | na64dp_dsul_update_extern_symbols( _buffer, &ctx ); | |
| 104 | } | ||
| 105 | /// Retruns `true` if given detector ID matches the expression | ||
| 106 | 40 | bool matches( PrincipalT pv ) const { | |
| 107 | // TODO: to-voidptr cast violates generocity; move to traits | ||
| 108 | 40 | na64dp_dsul_update_static_symbols( _buffer | |
| 109 | 40 | , (Principal_t) ((uintptr_t) pv) ); | |
| 110 | 40 | return na64dp_dsul_eval( _buffer ); | |
| 111 | } | ||
| 112 | /// Shortcut for `matches()` method | ||
| 113 | 5 | bool operator()( PrincipalT pv ) const { return matches(pv); } | |
| 114 | /// Dumps the evaluation buffer details into given stream | ||
| 115 | ✗ | void dump_eval_buffer(std::ostream & os) const { | |
| 116 | char * dump; | ||
| 117 | size_t dumpSize; | ||
| 118 | ✗ | FILE * dumpF = open_memstream( &dump, &dumpSize ); | |
| 119 | ✗ | na64dp_dsul_dump( _buffer, dumpF ); | |
| 120 | ✗ | fclose(dumpF); | |
| 121 | ✗ | os << std::string( dump, dumpSize ); | |
| 122 | ✗ | free(dump); | |
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 126 | } // namespace dsul | ||
| 127 | |||
| 128 | } | ||
| 129 | |||
| 130 | template< typename PrincipalT | ||
| 131 | , typename ContextT > std::ostream & | ||
| 132 | ✗ | operator<<(std::ostream & os, const na64dp::dsul::Selector<PrincipalT, ContextT> & s ) { | |
| 133 | ✗ | s.dump_eval_buffer(os); | |
| 134 | ✗ | return os; | |
| 135 | } | ||
| 136 | |||
| 137 |