Files @ r21584:561d516cfa45
Branch filter:

Location: cpp/openttd-patchpack/source/src/stringfilter_type.h

rubidium
(svn r26708) -Codechange: replace C preprocessor with all kinds of options to prevent adding certain things to the result and the sed script to remove everything that shouldn't be in the resulting nfo file but came out of the C preprocessor by a small-ish awk program. This means no more breaking if a C preprocessor decides to add more data to the processed file (like GCC's inclusion of stdc-predef.h when not passing -nostdinc). It furthermore more than halfs the time needed for the assemble step of the extra GRF compilation
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file stringfilter_type.h Searching and filtering using a stringterm. */

#ifndef STRINGFILTER_TYPE_H
#define STRINGFILTER_TYPE_H

#include "core/smallvec_type.hpp"
#include "strings_type.h"

/**
 * String filter and state.
 *
 * The filter takes a stringterm and parses it into words separated by whitespace.
 * The whitespace-separation can be avoided by quoting words in the searchterm using " or '.
 * The quotation characters can be nested or concatenated in a unix-shell style.
 *
 * When filtering an item, all words are checked for matches, and the filter matches if every word
 * matched. So, effectively this is a AND search for all entered words.
 *
 * Once the filter is set up using SetFilterTerm, multiple items can be filtered consecutively.
 *  1. For every item first call ResetState() which resets the matching-state.
 *  2. Pass all lines of the item via AddLine() to the filter.
 *  3. Check the matching-result for the item via GetState().
 */
struct StringFilter {
private:
	/** State of a single filter word */
	struct WordState {
		const char *start;                         ///< Word to filter for.
		bool match;                                ///< Already matched?
	};

	const char *filter_buffer;                     ///< Parsed filter string. Words separated by 0.
	SmallVector<WordState, 4> word_index;          ///< Word index and filter state.
	uint word_matches;                             ///< Summary of filter state: Number of words matched.

	const bool *case_sensitive;                    ///< Match case-sensitively (usually a static variable).

public:
	/**
	 * Constructor for filter.
	 * @param case_sensitive Pointer to a (usually static) variable controlling the case-sensitivity. NULL means always case-insensitive.
	 */
	StringFilter(const bool *case_sensitive = NULL) : filter_buffer(NULL), word_matches(0), case_sensitive(case_sensitive) {}
	~StringFilter() { free(this->filter_buffer); }

	void SetFilterTerm(const char *str);

	/**
	 * Check whether any filter words were entered.
	 * @return true if no words were entered.
	 */
	bool IsEmpty() const { return this->word_index.Length() == 0; }

	void ResetState();
	void AddLine(const char *str);
	void AddLine(StringID str);

	/**
	 * Get the matching state of the current item.
	 * @return true if matched.
	 */
	bool GetState() const { return this->word_matches == this->word_index.Length(); }
};

#endif /* STRINGFILTER_TYPE_H */