/**
 * Prefix Match
 *
 * Match input value to a list of options, allowing non-ambiguous abbreviation and partial matching.
 * This library was designed for command recognition in interactive consoles and command interfaces.
 * 
 * Created on 2020/06/09 by Ondřej Hruška
 */

#ifndef _PREFIX_MATCH_H
#define _PREFIX_MATCH_H

#include <stdbool.h>
#include <stddef.h>

/** Use case-sensitive matching */
#define PREFIXMATCH_CASE_SENSITIVE 1
/** Forbid abbreviations */
#define PREFIXMATCH_NOABBREV 2
/** Allow matching fewer words, if unambiguous */
#define PREFIXMATCH_MULTI_PARTIAL 4

enum pm_test_result {
    PM_TEST_NO_MATCH = 0,
    PM_TEST_MATCH = 1,
    PM_TEST_MATCH_MULTI_PARTIAL = 2,
};

/**
 * Recognize (optionally abbreviated) input
 *
 * @param[in] value - tested value
 * @param[in] options - options to match against
 * @param[in] flags - matching options (bitmask) - accepts PREFIXMATCH_CASE_SENSITIVE and PREFIXMATCH_NOABBREV
 * @return index of the matched option, -1 on mismatch or ambiguous match
 */
int prefix_match(const char *value, const char **options, int flags);

/**
 * Recognize input consisting of one or more (optionally abbreviated) words
 *
 * @param[in] value - tested value
 * @param[in] options - options to match against, multi-word options separated by the listed delimiters
 * @param[in] delims - string with a list of possible delimiters (like for strtok)
 * @param[in] flags - matching options (bitmask) - accepts all options
 * @return index of the matched option, -1 on mismatch or ambiguous match
 */
int prefix_multipart_match(const char *restrict value, const char **options, const char* restrict delims, int flags);

// useful internal functions exported for possible re-use

/**
 * Test if two word sentences match, with individual words optionally allowed to be abbreviated.
 *
 * @internal
 * @param[in] tested - tested (optionally abbreviated) sentence
 * @param[in] full - full sentence
 * @param[in] delims - list of possible delimiters, same may be used for both sentences
 * @param[in] flags - matching options (bitmask) - accepts all options
 * @return 1-match; 0-no match; 2-partial (some words) match, if the PREFIXMATCH_MULTI_PARTIAL flag is set
 */
enum pm_test_result prefix_multipart_test(const char *restrict tested, const char* restrict full, const char *restrict delims, int flags);

/**
 * Count words in a "sentence", delimited by any of the given set of delimiters.
 *
 * @internal
 * @param[in] sentence - one or multi-word string
 * @param[in] delims - delimiters accepted
 * @return number of words
 */
size_t pm_count_words(const char * restrict sentence, const char * restrict delims);

/**
 * Measure word length
 *
 * @internal
 * @param[in] word - start of a word that ends with either one of the delimiters, or a null byte.
 * @param[in] delims - delimiters accepted
 * @return word length
 */
size_t pm_word_len(const char * restrict word, const char * restrict delims);

/**
 * Skip N words in a sentence.
 *
 * @param[in] sentence - one or multi-word string
 * @param[in] delims - delimiters accepted
 * @param[in] skip - how many words to skip
 * @return pointer to the first byte after the last skipped word
 */
const char *pm_skip_words(const char * restrict sentence, const char * restrict delims, size_t skip);

#endif //_PREFIX_MATCH_H