1 #pragma once
2 #ifndef CATA_SRC_ITEM_SEARCH_H
3 #define CATA_SRC_ITEM_SEARCH_H
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <functional>
8 #include <iosfwd>
9 #include <string>
10 #include <vector>
11
12 #include "output.h"
13
14 /**
15 * Get a function that returns true if the value matches the query.
16 */
17 template<typename T>
filter_from_string(std::string filter,std::function<std::function<bool (const T &)> (const std::string &)> basic_filter)18 std::function<bool( const T & )> filter_from_string( std::string filter,
19 std::function<std::function<bool( const T & )>( const std::string & )> basic_filter )
20 {
21 if( filter.empty() ) {
22 // Variable without name prevents unused parameter warning
23 return []( const T & ) {
24 return true;
25 };
26 }
27
28 // remove curly braces (they only get in the way)
29 if( filter.find( '{' ) != std::string::npos ) {
30 filter.erase( std::remove( filter.begin(), filter.end(), '{' ), filter.end() );
31 }
32 if( filter.find( '}' ) != std::string::npos ) {
33 filter.erase( std::remove( filter.begin(), filter.end(), '}' ), filter.end() );
34 }
35 if( filter.find( ',' ) != std::string::npos ) {
36 // functions which only one of which must return true
37 std::vector<std::function<bool( const T & )> > functions;
38 // Functions that must all return true
39 std::vector<std::function<bool( const T & )> > inv_functions;
40 size_t comma = filter.find( ',' );
41 while( !filter.empty() ) {
42 const auto ¤t_filter = trim( filter.substr( 0, comma ) );
43 if( !current_filter.empty() ) {
44 auto current_func = filter_from_string( current_filter, basic_filter );
45 if( current_filter[0] == '-' ) {
46 inv_functions.push_back( current_func );
47 } else {
48 functions.push_back( current_func );
49 }
50 }
51 if( comma != std::string::npos ) {
52 filter = trim( filter.substr( comma + 1 ) );
53 comma = filter.find( ',' );
54 } else {
55 break;
56 }
57 }
58
59 return [functions, inv_functions]( const T & it ) {
60 auto apply = [&]( const std::function<bool( const T & )> &func ) {
61 return func( it );
62 };
63 const bool p_result = std::any_of( functions.begin(), functions.end(),
64 apply );
65 const bool n_result = std::all_of(
66 inv_functions.begin(),
67 inv_functions.end(),
68 apply );
69 if( !functions.empty() && inv_functions.empty() ) {
70 return p_result;
71 }
72 if( functions.empty() && !inv_functions.empty() ) {
73 return n_result;
74 }
75 return p_result && n_result;
76 };
77 }
78 const bool exclude = filter[0] == '-';
79 if( exclude ) {
80 return [filter, basic_filter]( const T & i ) {
81 return !filter_from_string( filter.substr( 1 ), basic_filter )( i );
82 };
83 }
84
85 return basic_filter( filter );
86 }
87
88 class item;
89
90 /**
91 * Get a function that returns true if the item matches the query.
92 */
93 std::function<bool( const item & )> item_filter_from_string( const std::string &filter );
94
95 /**
96 * Get a function that returns true if the value matches the basic query (no commas or minuses).
97 */
98 std::function<bool( const item & )> basic_item_filter( std::string filter );
99
100 #endif // CATA_SRC_ITEM_SEARCH_H
101