예제 #1
0
bool_t
NOTQuery_equals(NOTQuery *self, Obj *other)
{
    if ((NOTQuery*)other == self)   { return true; }
    if (!OBJ_IS_A(other, NOTQUERY)) { return false; }
    return PolyQuery_equals((PolyQuery*)self, other);
}
예제 #2
0
bool_t
Tokenizer_equals(Tokenizer *self, Obj *other)
{
    Tokenizer *const evil_twin = (Tokenizer*)other;
    if (evil_twin == self) return true;
    if (!OBJ_IS_A(evil_twin, TOKENIZER)) return false;
    if (!CB_Equals(evil_twin->pattern, (Obj*)self->pattern)) return false;
    return true;
}
예제 #3
0
void
HLWriter_add_inverted_doc(HighlightWriter *self, Inverter *inverter, 
                          i32_t doc_id)
{
    OutStream *dat_out = S_lazy_init(self);
    OutStream *ix_out  = self->ix_out;
    i64_t      filepos = OutStream_Tell(dat_out);
    u32_t num_highlightable = 0;
    i32_t expected = (i32_t)(OutStream_Tell(ix_out) / 8);

    /* Verify doc id. */
    if (doc_id != expected)
        THROW("Expected doc id %i32 but got %i32", expected, doc_id);

    /* Write index data. */
    OutStream_Write_U64(ix_out, filepos);

    /* Count, then write number of highlightable fields. */
    Inverter_Iter_Init(inverter);
    while (Inverter_Next(inverter)) {
        FieldType *type = Inverter_Get_Type(inverter);
        if (   OBJ_IS_A(type, FULLTEXTTYPE) 
            && FullTextType_Highlightable(type)
        ) {
            num_highlightable++;
        }
    }
    OutStream_Write_C32(dat_out, num_highlightable);

    Inverter_Iter_Init(inverter);
    while (Inverter_Next(inverter)) {
        FieldType *type = Inverter_Get_Type(inverter);
        if (   OBJ_IS_A(type, FULLTEXTTYPE) 
            && FullTextType_Highlightable(type)
        ) {
            CharBuf   *field     = Inverter_Get_Field_Name(inverter);
            Inversion *inversion = Inverter_Get_Inversion(inverter);
            ByteBuf   *tv_buf    = HLWriter_TV_Buf(self, inversion);
            CB_Serialize(field, dat_out);
            BB_Serialize(tv_buf, dat_out);
            DECREF(tv_buf);
        }
    }
}
예제 #4
0
void
LexIndex_seek(LexIndex *self, Obj *target)
{
    FieldType   *type   = self->field_type;
    i32_t        lo     = 0;
    i32_t        hi     = self->size - 1;
    i32_t        result = -100;

    if (target == NULL || self->size == 0) { 
        self->tick = 0;
        return;
    }
    else {
        if ( !OBJ_IS_A(target, CHARBUF)) {
            THROW("Target is a %o, and not comparable to a %o",
                Obj_Get_Class_Name(target), CHARBUF.name);
        }
        /* TODO: 
        Obj *first_obj = VA_Fetch(terms, 0);
        if ( !Obj_Is_A(target, Obj_Get_VTable(first_obj)) ) {
            THROW("Target is a %o, and not comparable to a %o",
                Obj_Get_Class_Name(target), Obj_Get_Class_Name(first_obj));
        }
        */
    }

    /* Divide and conquer. */
    while (hi >= lo) {
        const i32_t mid = lo + ((hi - lo) / 2);
        const i64_t offset 
            = (i64_t)Math_decode_bigend_u64(self->offsets + mid);
        char *data = self->data + offset;
        size_t size = Math_decode_c32(&data);
        i64_t comparison;

        ViewCB_Assign_Str(self->term, data, size);
        comparison = FType_Compare_Values(type, target, (Obj*)self->term);
        if (comparison < 0) {
            hi = mid - 1;
        }
        else if (comparison > 0) {
            lo = mid + 1;
        }
        else {
            result = mid;
            break;
        }
    }

    /* Record the index of the entry we've seeked to, then read entry. */
    self->tick = hi == -1   ? 0  /* indicating that target lt first entry */
           : result == -100 ? hi /* if result is still -100, it wasn't set */
           : result;
    S_read_entry(self);
}
예제 #5
0
bool_t
PhraseCompiler_equals(PhraseCompiler *self, Obj *other)
{
    PhraseCompiler *evil_twin = (PhraseCompiler*)other;
    if (!OBJ_IS_A(evil_twin, PHRASECOMPILER)) return false;
    if (!Compiler_equals((Compiler*)self, other)) return false;
    if (self->idf != evil_twin->idf) return false;
    if (self->raw_weight != evil_twin->raw_weight) return false;
    if (self->query_norm_factor != evil_twin->query_norm_factor) return false;
    if (self->normalized_weight != evil_twin->normalized_weight) return false;
    return true;
}
예제 #6
0
bool_t
PhraseQuery_equals(PhraseQuery *self, Obj *other)
{
    PhraseQuery *evil_twin = (PhraseQuery*)other;
    if (evil_twin == self) return true;
    if (!OBJ_IS_A(evil_twin, PHRASEQUERY)) return false;
    if (self->boost != evil_twin->boost) return false;
    if (self->field && !evil_twin->field) return false;
    if (!self->field && evil_twin->field) return false;
    if (self->field && !CB_Equals(self->field, (Obj*)evil_twin->field)) 
        return false;
    if (!VA_Equals(evil_twin->terms, (Obj*)self->terms)) return false;
    return true;
}
예제 #7
0
Matcher*
PhraseCompiler_make_matcher(PhraseCompiler *self, SegReader *reader,
                            bool_t need_score)
{
    PostingsReader *const post_reader = (PostingsReader*)SegReader_Fetch(
        reader, POSTINGSREADER.name);
    PhraseQuery *const parent = (PhraseQuery*)self->parent;
    VArray  *const terms      = parent->terms;
    u32_t    num_terms        = VA_Get_Size(terms);
    Schema  *schema           = SegReader_Get_Schema(reader);
    Posting *posting          = Schema_Fetch_Posting(schema, parent->field);
    VArray  *plists;
    Matcher *retval;
    u32_t i;
    UNUSED_VAR(need_score);

    /* Bail if there are no terms. */
    if (!num_terms) return NULL;

    /* Bail unless field is valid and posting type supports positions. */
    if (posting == NULL || !OBJ_IS_A(posting, SCOREPOSTING)) return NULL;

    /* Bail if there's no PostingsReader for this segment. */
    if (!post_reader) { return NULL; }

    /* Look up each term. */
    plists = VA_new(num_terms);
    for (i = 0; i < num_terms; i++) {
        Obj *term = VA_Fetch(terms, i);
        PostingList *plist 
            = PostReader_Posting_List(post_reader, parent->field, term);

        /* Bail if any one of the terms isn't in the index. */
        if (!plist || !PList_Get_Doc_Freq(plist)) {
            DECREF(plist);
            DECREF(plists);
            return NULL;
        }
        VA_Push(plists, (Obj*)plist);
    }

    retval = (Matcher*)PhraseScorer_new(
        Compiler_Get_Similarity(self),
        plists, 
        (Compiler*)self
    );
    DECREF(plists);

    return retval;
}
예제 #8
0
i32_t
SortCache_find(SortCache *self, Obj *term)
{
    FieldType *const type = self->type;
    i32_t          lo     = 0;
    i32_t          hi     = self->num_uniq - 1;
    i32_t          result = -100;
    ZombieCharBuf  value  = ZCB_BLANK;

    if ( term != NULL && !OBJ_IS_A(term, CHARBUF)) {
        THROW("term is a %o, and not comparable to a %o",
            Obj_Get_Class_Name(term), CHARBUF.name);
    }

    /* Binary search. */
    while (hi >= lo) {
        const i32_t mid = lo + ((hi - lo) / 2);
        ViewCharBuf *val = SortCache_Value(self, mid, (ViewCharBuf*)&value);
        i64_t comparison = FType_Compare_Values(type, term, (Obj*)val);
        if (comparison < 0) {
            hi = mid - 1;
        }
        else if (comparison > 0) {
            lo = mid + 1;
        }
        else {
            result = mid;
            break;
        }
    }

    if (hi < 0) { 
        /* Target is "less than" the first cache entry. */
        return -1;
    }
    else if (result == -100) {
        /* If result is still -100, it wasn't set. */
        return hi;
    }
    else {
        return result;
    }
}
예제 #9
0
Matcher*
NOTCompiler_make_matcher(NOTCompiler *self, SegReader *reader, 
                         bool_t need_score)
{
    Matcher *negated_matcher 
        = Compiler_Make_Matcher(VA_Fetch(self->children, 0), reader, false);
    UNUSED_VAR(need_score);

    if (negated_matcher == NULL) {
        float weight = Compiler_Get_Weight(self);
        return (Matcher*)MatchAllScorer_new(weight, SegReader_Doc_Max(reader));
    }
    else if (OBJ_IS_A(negated_matcher, MATCHALLSCORER)) {
        DECREF(negated_matcher);
        return NULL;
    }
    else {
        Matcher *retval 
            = (Matcher*)NOTScorer_new(negated_matcher, SegReader_Doc_Max(reader));
        DECREF(negated_matcher);
        return retval;
    }
}
/// Constructs a GSList list of @ref FrameSet objects from a datagram/packet.
/// That is, it decodes the datagram/packet.
/// @return GSList of @ref FrameSet object pointers.
GSList*
_pktdata_to_framesetlist(PacketDecoder*self,		///<[in] PacketDecoder object
			 gpointer pktstart,		///<[in] start of packet
			 gconstpointer pktend)		///<[in] first byte past end of packet
{
	guint8*		curframeset = pktstart;
	GSList*		ret = NULL;

	// Loop over all the FrameSets in the packet we were given.
	while (curframeset < (guint8*)pktend) {
		gpointer	nextframeset = NULL;
		gpointer	framestart = ((guint8*)curframeset + FRAMESET_INITSIZE);
		gpointer	curframe;
		FrameSet*	fs;
		gconstpointer	fsend = pktend;
		gpointer	newframestart = NULL;
		gboolean	firstframe = TRUE;
		guint32		framesetlen;

		// Check the overall frame size
		framesetlen = get_generic_tlv_len(curframeset, pktend);
		if (framesetlen > (guint32)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE))) {
			g_warning("%s.%d: Received frameset length [%d] is invalid - cannot exceed %d"
			,	__FUNCTION__, __LINE__, framesetlen
			,	(int)((guint8*)pktend-(curframeset+FRAMESET_INITSIZE)));
			goto errout;
		}
		fsend = curframeset+framesetlen+FRAMESET_INITSIZE;
		fs = _decode_packet_get_frameset_data(curframeset, curframeset+framesetlen, &nextframeset);
		g_return_val_if_fail(fs != NULL,  ret);
		if (!is_valid_generic_tlv_packet(framestart, pktend)) {
			g_warning("%s.%d:  Frameset type %d not a valid TLV frameset"
			,	__FUNCTION__, __LINE__, fs->fstype);
			UNREF(fs);
			goto errout;
		}

		// Construct this FrameSet from the series of frames encoded in the packet.
		// Note that two special kinds of frames can alter the packet we're examining.
		// This is explained in more detail inside the loop.
		curframe = framestart;
		while (curframe != NULL && curframe < fsend) {
			Frame*		newframe;
			gpointer	newpacket = NULL;
			// The first special case frame is the compression frame, in which case the
			// remaining packet is replaced by a new, larger (decompressed) packet.
			//
			// The second type is the encryption packet, in which case the remaining
			// packet is replaced by a new chunk of data which will have different
			// (decrypted) content, and would normally be expected to be the same size
			// as the original.
			//
			// This means that "decode_packet_framedata_to_frameobject" might replace the
			// packet data we've been looking at.
			// (FWIW: It's perfectly OK to have an encryption frame followed by a
			// (embedded) compression frame -- both kinds can occur in the same FrameSet).
			newframe = _decode_packet_framedata_to_frameobject(self, &curframe, &fsend, &newpacket);
			if (newpacket) {
				if (newframestart != NULL) {
					// We did packet replacement more than once...
					g_free(newframestart);
				}
				newframestart = newpacket;
			}
			if (NULL == newframe) {
				UNREF(fs);
				goto errout;
			}
			if (TRUE == firstframe) {
				if (!OBJ_IS_A(newframe, "SignFrame")) {
					UNREF(newframe);
					UNREF(fs);
					g_warning("%s.%d: First frame NOT a signature frame - [%d] instead"
					,	__FUNCTION__, __LINE__, newframe->type);
					goto errout;
				}
				firstframe = FALSE;
			}
			frameset_append_frame(fs, newframe);
			UNREF(newframe);
		}
		if (curframe != fsend) {
			g_warning("%s.%d:  Received %d frameset - length is off by"
			": %d instead"
			,	__FUNCTION__, __LINE__, fs->fstype
			,	(int)((guint8*)fsend-((guint8*)curframe)));
			goto errout;
		}
		if (newframestart) {
			g_free(newframestart); newframestart = NULL;
		}
		if (fs) {
			ret = g_slist_append(ret, fs); fs = NULL;
		}
		curframeset = nextframeset;
	}
	return ret;
errout:
	g_slist_free_full(ret, assim_g_notify_unref); ret = NULL;
	return ret;
}