#include <stdlib.h>
#include "svn_string.h"
#include "cl.h"
#include "private/svn_string_private.h"
#include "svn_private_config.h"
struct svn_cl__simcheck_context_t
{
svn_string_t key;
svn_membuf_t buffer;
};
static APR_INLINE apr_size_t
simcheck_key_diff(const svn_string_t *key, const svn_string_t *ctx,
svn_membuf_t *buffer, apr_size_t *diff)
{
apr_size_t lcs;
const apr_size_t score = svn_string__similarity(key, ctx, buffer, &lcs);
if (key->len > ctx->len)
*diff = key->len - lcs;
else
*diff = ctx->len - lcs;
return score;
}
static int
simcheck_compare(const void *pkeya, const void *pkeyb)
{
svn_cl__simcheck_t *const keya = *(svn_cl__simcheck_t *const *)pkeya;
svn_cl__simcheck_t *const keyb = *(svn_cl__simcheck_t *const *)pkeyb;
svn_cl__simcheck_context_t *const context = keya->context;
if (keya->score == -1)
keya->score = simcheck_key_diff(&keya->token, &context->key,
&context->buffer, &keya->diff);
if (keyb->score == -1)
keyb->score = simcheck_key_diff(&keyb->token, &context->key,
&context->buffer, &keyb->diff);
return (keya->score < keyb->score ? 1
: (keya->score > keyb->score ? -1
: (keya->diff > keyb->diff ? 1
: (keya->diff < keyb->diff ? -1 : 0))));
}
apr_size_t
svn_cl__similarity_check(const char *key,
svn_cl__simcheck_t **tokens,
apr_size_t token_count,
apr_pool_t *scratch_pool)
{
apr_size_t result;
apr_size_t i;
svn_cl__simcheck_context_t context;
context.key.data = key;
context.key.len = strlen(key);
svn_membuf__create(&context.buffer, 0, scratch_pool);
for (i = 0; i < token_count; ++i)
{
svn_cl__simcheck_t *const token = tokens[i];
token->score = -1;
token->diff = 0;
token->context = &context;
}
qsort(tokens, token_count, sizeof(*tokens), simcheck_compare);
for (i = 0, result = 1; i < token_count; ++i)
{
svn_cl__simcheck_t *const token = tokens[i];
token->context = NULL;
if (token->score >= (2 * SVN_STRING__SIM_RANGE_MAX + 1) / 3)
++result;
}
if (0 == tokens[0]->diff)
return 0;
return result;
}