@@ -110,6 +110,30 @@ 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 enforces equal size pattern and mask arrays at compile time.
114+ template <size_t N>
115+ constexpr MaskedATREntry (const byte_type (&_pat)[N], const byte_type (&_mask)[N],
116+ ElectronicIDConstructor&& _constructor) :
117+ pattern(std::begin(_pat), std::end(_pat)), mask(std::begin(_mask), std::end(_mask)),
118+ constructor(std::move(_constructor))
119+ {
120+ }
121+
122+ bool operator ==(const byte_vector& atr) const
123+ {
124+ if (atr.size () != pattern.size ()) {
125+ return false ;
126+ }
127+
128+ for (size_t i = 0 ; i < atr.size (); ++i) {
129+ if ((atr[i] & mask[i]) != (pattern[i] & mask[i])) {
130+ return false ;
131+ }
132+ }
133+
134+ return true ;
135+ }
136+
113137 byte_vector pattern;
114138 byte_vector mask;
115139 ElectronicIDConstructor constructor;
@@ -135,26 +159,6 @@ std::string byteVectorToHexString(const byte_vector& bytes)
135159 return hexStringBuilder.str ();
136160}
137161
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-
158162const auto SUPPORTED_ALGORITHMS = std::map<std::string, HashAlgorithm> {
159163 {" SHA-224" s, HashAlgorithm::SHA224}, {" SHA-256" s, HashAlgorithm::SHA256},
160164 {" SHA-384" s, HashAlgorithm::SHA384}, {" SHA-512" s, HashAlgorithm::SHA512},
@@ -169,10 +173,9 @@ namespace electronic_id
169173
170174std::optional<ElectronicIDConstructor> findMaskedATR (const byte_vector& atr)
171175{
172- for (const auto & entry : MASKED_ATRS) {
173- if (matchATRWithMask (atr, entry.pattern , entry.mask )) {
174- return entry.constructor ;
175- }
176+ if (auto i = std::find (MASKED_ATRS.cbegin (), MASKED_ATRS.cend (), atr);
177+ i != MASKED_ATRS.cend ()) {
178+ return i->constructor ;
176179 }
177180 return std::nullopt ;
178181}
0 commit comments