#include "KinoSearch/Util/ToolSet.h"
#define KINO_WANT_SORTCOLLECTOR_VTABLE
#include "KinoSearch/Search/SortCollector.r"
#include "KinoSearch/Search/FieldDoc.r"
#include "KinoSearch/Search/FieldDocCollator.r"
#include "KinoSearch/Search/HitQueue.r"
#include "KinoSearch/Search/SortedHitQueue.r"
static void
SortColl_collect(SortCollector *self, u32_t doc_num, float score);
SortCollector*
SortColl_new(FieldDocCollator *collator, u32_t num_hits)
{
CREATE(self, SortCollector, SORTCOLLECTOR);
/* init */
self->collect = (HC_collect_t)SortColl_collect;
self->release = NULL; /* not needed, destroy overridden */
self->data = NULL; /* not needed */
self->min_doc = -1;
self->min_score = 0.0f;
self->total_hits = 0;
self->num_hits = 0;
/* assign */
self->num_hits = num_hits;
self->collator = REFCOUNT_INC(collator);
/* derive */
self->hit_q = (HitQueue*)SortedHitQ_new(num_hits);
return self;
}
void
SortColl_destroy(SortCollector *self)
{
REFCOUNT_DEC(self->collator);
REFCOUNT_DEC(self->hit_q);
free(self);
}
static void
SortColl_collect(SortCollector *self, u32_t doc_num, float score)
{
/* add to the total number of hits */
self->total_hits++;
/* bail if the doc doesn't sort higher than the current bubble */
if ( self->total_hits > self->num_hits
&& ( FDocCollator_Compare(self->collator, doc_num, score,
self->min_doc, self->min_score) )
) {
return;
}
else {
FieldDoc *const field_doc
= FieldDoc_new(doc_num, score, self->collator);
SortedHitQueue *const hit_q = (SortedHitQueue*)self->hit_q;
SortedHitQ_Insert(hit_q, field_doc);
/* store the bubble score in a more accessible spot */
if (hit_q->size == hit_q->max_size) {
FieldDoc *const least = (FieldDoc*)SortedHitQ_Peek(hit_q);
self->min_doc = least->doc_num;
self->min_score = least->score;
}
}
}
/* Copyright 2007 Marvin Humphrey
*
* This program is free software; you can redistribute it and/or modify
* under the same terms as Perl itself.
*/