/* Copyright (c) Pigeonhole authors, see top-level COPYING file */

#include "lib.h"
#include "str.h"

#include "sieve-common.h"

#include "sieve-ast.h"
#include "sieve-code.h"
#include "sieve-extensions.h"
#include "sieve-commands.h"
#include "sieve-comparators.h"
#include "sieve-match-types.h"
#include "sieve-validator.h"
#include "sieve-generator.h"
#include "sieve-interpreter.h"
#include "sieve-match.h"

#include "ext-relational-common.h"

/*
 * Match-type objects
 */

const struct sieve_match_type_def value_match_type = {
	SIEVE_OBJECT("value", &rel_match_type_operand, RELATIONAL_VALUE),
	.validate = mcht_relational_validate,
};

#define VALUE_MATCH_TYPE(name, rel_match)                           \
const struct sieve_match_type_def rel_match_value_ ## name = {      \
	SIEVE_OBJECT("value-" #name,                                \
		     &rel_match_type_operand,                       \
		     REL_MATCH_INDEX(RELATIONAL_VALUE, rel_match)), \
	.match_key = mcht_value_match_key,                          \
}

VALUE_MATCH_TYPE(gt, REL_MATCH_GREATER);
VALUE_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL);
VALUE_MATCH_TYPE(lt, REL_MATCH_LESS);
VALUE_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL);
VALUE_MATCH_TYPE(eq, REL_MATCH_EQUAL);
VALUE_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL);

/*
 * Match-type implementation
 */

int mcht_value_match_key(struct sieve_match_context *mctx,
			 const char *val, size_t val_size,
			 const char *key, size_t key_size)
{
	const struct sieve_match_type *mtch = mctx->match_type;
	unsigned int rel_match = REL_MATCH(mtch->object.def->code);
	int cmp_result;

	cmp_result = mctx->comparator->def->compare(
		mctx->comparator, val, val_size, key, key_size);

	switch (rel_match) {
	case REL_MATCH_GREATER:
		return (cmp_result > 0 ? 1 : 0);
	case REL_MATCH_GREATER_EQUAL:
		return (cmp_result >= 0 ? 1 : 0);
	case REL_MATCH_LESS:
		return (cmp_result < 0 ? 1 : 0);
	case REL_MATCH_LESS_EQUAL:
		return (cmp_result <= 0 ? 1 : 0);
	case REL_MATCH_EQUAL:
		return (cmp_result == 0 ? 1 : 0);
	case REL_MATCH_NOT_EQUAL:
		return (cmp_result != 0 ? 1 : 0);
	}
	i_unreached();
}
