@@ -110,6 +110,31 @@ const std::map<byte_vector, ElectronicIDConstructor> SUPPORTED_ATRS {
110110// Holds ATR pattern, mask, and constructor for variable ATR cards.
111111struct MaskedATREntry
112112{
113+ // Single template parameter assures that the pattern and mask arrays are of equal size
114+ // at compile time.
115+ template <size_t N>
116+ constexpr MaskedATREntry (const byte_type (&_pat)[N], const byte_type (&_mask)[N],
117+ ElectronicIDConstructor&& _constructor) :
118+ pattern(std::begin(_pat), std::end(_pat)), mask(std::begin(_mask), std::end(_mask)),
119+ constructor(std::move(_constructor))
120+ {
121+ }
122+
123+ bool operator ==(const byte_vector& atr) const
124+ {
125+ if (atr.size () != pattern.size ()) {
126+ return false ;
127+ }
128+
129+ for (size_t i = 0 ; i < atr.size (); ++i) {
130+ if ((atr[i] & mask[i]) != (pattern[i] & mask[i])) {
131+ return false ;
132+ }
133+ }
134+
135+ return true ;
136+ }
137+
113138 byte_vector pattern;
114139 byte_vector mask;
115140 ElectronicIDConstructor constructor;
@@ -135,26 +160,6 @@ std::string byteVectorToHexString(const byte_vector& bytes)
135160 return hexStringBuilder.str ();
136161}
137162
138- bool matchATRWithMask (const byte_vector& atr, const byte_vector& pattern, const byte_vector& mask)
139- {
140- if (pattern.size () != mask.size ()) {
141- THROW (ProgrammingError,
142- " MaskedATREntry '" + byteVectorToHexString (pattern)
143- + " ' pattern size does not match mask size" );
144- }
145-
146- if (atr.size () != pattern.size ()) {
147- return false ;
148- }
149- for (size_t i = 0 ; i < atr.size (); ++i) {
150- if ((atr[i] & mask[i]) != (pattern[i] & mask[i])) {
151- return false ;
152- }
153- }
154-
155- return true ;
156- }
157-
158163const auto SUPPORTED_ALGORITHMS = std::map<std::string, HashAlgorithm> {
159164 {" SHA-224" s, HashAlgorithm::SHA224}, {" SHA-256" s, HashAlgorithm::SHA256},
160165 {" SHA-384" s, HashAlgorithm::SHA384}, {" SHA-512" s, HashAlgorithm::SHA512},
@@ -169,10 +174,9 @@ namespace electronic_id
169174
170175std::optional<ElectronicIDConstructor> findMaskedATR (const byte_vector& atr)
171176{
172- for (const auto & entry : MASKED_ATRS) {
173- if (matchATRWithMask (atr, entry.pattern , entry.mask )) {
174- return entry.constructor ;
175- }
177+ if (auto i = std::find (MASKED_ATRS.cbegin (), MASKED_ATRS.cend (), atr);
178+ i != MASKED_ATRS.cend ()) {
179+ return i->constructor ;
176180 }
177181 return std::nullopt ;
178182}
0 commit comments