| 196 | |
| 197 | template <typename PatternIterator> |
| 198 | constexpr PatternIterator set_end( |
| 199 | PatternIterator p, PatternIterator pend, |
| 200 | const cards<iterated_item_t<PatternIterator>>& c = cards<iterated_item_t<PatternIterator>>(), |
| 201 | set_end_state state = set_end_state::open) |
| 202 | { |
| 203 | #if cfg_HAS_CONSTEXPR14 |
| 204 | |
| 205 | if (!c.set_enabled) |
| 206 | { |
| 207 | #if cfg_HAS_FULL_FEATURED_CONSTEXPR14 |
| 208 | throw std::invalid_argument("The use of sets is disabled"); |
| 209 | #else |
| 210 | return throw_invalid_argument(p, "The use of sets is disabled"); |
| 211 | #endif |
| 212 | } |
| 213 | |
| 214 | while (p != pend) |
| 215 | { |
| 216 | switch (state) |
| 217 | { |
| 218 | case set_end_state::open: |
| 219 | if (*p != c.set_open) |
| 220 | { |
| 221 | #if cfg_HAS_FULL_FEATURED_CONSTEXPR14 |
| 222 | throw std::invalid_argument("The given pattern is not a valid set"); |
| 223 | #else |
| 224 | return throw_invalid_argument(p, "The given pattern is not a valid set"); |
| 225 | #endif |
| 226 | } |
| 227 | |
| 228 | state = set_end_state::not_or_first; |
| 229 | break; |
| 230 | |
| 231 | case set_end_state::not_or_first: |
| 232 | if (*p == c.set_not) |
| 233 | { |
| 234 | state = set_end_state::first; |
| 235 | } |
| 236 | else |
| 237 | { |
| 238 | state = set_end_state::next; |
| 239 | } |
| 240 | |
| 241 | break; |
| 242 | |
| 243 | case set_end_state::first: |
| 244 | state = set_end_state::next; |
| 245 | break; |
| 246 | |
| 247 | case set_end_state::next: |
| 248 | if (*p == c.set_close) |
| 249 | { |
| 250 | return cx::next(p); |
| 251 | } |
| 252 | |
| 253 | break; |
| 254 | |
| 255 | default: |
no test coverage detected