static void test_Cat(TestBatch *batch) { CharBuf *wanted = CB_newf("a%s", smiley); CharBuf *got = S_get_cb(""); CB_Cat(got, wanted); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat"); DECREF(got); got = S_get_cb("a"); CB_Cat_Char(got, 0x263A); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Char"); DECREF(got); got = S_get_cb("a"); CB_Cat_Str(got, smiley, smiley_len); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Str"); DECREF(got); got = S_get_cb("a"); CB_Cat_Trusted_Str(got, smiley, smiley_len); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str"); DECREF(got); DECREF(wanted); }
bool_t TV_equals(TermVector *self, Obj *other) { TermVector *const evil_twin = (TermVector*)other; u32_t i; i32_t *const posits = self->positions->ints; i32_t *const starts = self->start_offsets->ints; i32_t *const ends = self->start_offsets->ints; i32_t *const other_posits = evil_twin->positions->ints; i32_t *const other_starts = evil_twin->start_offsets->ints; i32_t *const other_ends = evil_twin->start_offsets->ints; if (evil_twin == self) return true; if (!CB_Equals(self->field, (Obj*)evil_twin->field)) return false; if (!CB_Equals(self->text, (Obj*)evil_twin->text)) return false; if (self->num_pos != evil_twin->num_pos) return false; for (i = 0; i < self->num_pos; i++) { if (posits[i] != other_posits[i]) return false; if (starts[i] != other_starts[i]) return false; if (ends[i] != other_ends[i]) return false; } return true; }
bool_t LFLock_maybe_delete_file(LockFileLock *self, const CharBuf *path, bool_t delete_mine, bool_t delete_other) { Folder *folder = self->folder; bool_t success = false; ZombieCharBuf *scratch = ZCB_WRAP(path); // Only delete locks that start with our lock name. CharBuf *lock_dir_name = (CharBuf*)ZCB_WRAP_STR("locks", 5); if (!ZCB_Starts_With(scratch, lock_dir_name)) { return false; } ZCB_Nip(scratch, CB_Get_Size(lock_dir_name) + 1); if (!ZCB_Starts_With(scratch, self->name)) { return false; } // Attempt to delete dead lock file. if (Folder_Exists(folder, path)) { Hash *hash = (Hash*)Json_slurp_json(folder, path); if (hash != NULL && Obj_Is_A((Obj*)hash, HASH)) { CharBuf *pid_buf = (CharBuf*)Hash_Fetch_Str(hash, "pid", 3); CharBuf *host = (CharBuf*)Hash_Fetch_Str(hash, "host", 4); CharBuf *name = (CharBuf*)Hash_Fetch_Str(hash, "name", 4); // Match hostname and lock name. if (host != NULL && CB_Equals(host, (Obj*)self->host) && name != NULL && CB_Equals(name, (Obj*)self->name) && pid_buf != NULL ) { // Verify that pid is either mine or dead. int pid = (int)CB_To_I64(pid_buf); if ((delete_mine && pid == PID_getpid()) // This process. || (delete_other && !PID_active(pid)) // Dead pid. ) { if (Folder_Delete(folder, path)) { success = true; } else { CharBuf *mess = MAKE_MESS("Can't delete '%o'", path); DECREF(hash); Err_throw_mess(ERR, mess); } } } } DECREF(hash); } return success; }
static void test_Set_Path_and_Get_Path(TestBatch *batch) { Folder *folder = (Folder*)RAMFolder_new(&foo); TEST_TRUE(batch, CB_Equals(Folder_Get_Path(folder), (Obj*)&foo), "Get_Path"); Folder_Set_Path(folder, &bar); TEST_TRUE(batch, CB_Equals(Folder_Get_Path(folder), (Obj*)&bar), "Set_Path"); DECREF(folder); }
static void test_all(TestBatch *batch) { CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3); CharBuf *boffo = (CharBuf*)ZCB_WRAP_STR("boffo", 5); CharBuf *foo_boffo = (CharBuf*)ZCB_WRAP_STR("foo/boffo", 9); CharBuf *test_dir = (CharBuf*)ZCB_WRAP_STR("_fsdir_test", 11); FSFolder *folder = FSFolder_new(test_dir); bool_t saw_foo = false; bool_t saw_boffo = false; bool_t foo_was_dir = false; bool_t boffo_was_dir = false; int count = 0; // Clean up after previous failed runs. FSFolder_Delete(folder, foo_boffo); FSFolder_Delete(folder, foo); FSFolder_Delete(folder, boffo); rmdir("_fsdir_test"); FSFolder_Initialize(folder); FSFolder_MkDir(folder, foo); OutStream *outstream = FSFolder_Open_Out(folder, boffo); DECREF(outstream); outstream = FSFolder_Open_Out(folder, foo_boffo); DECREF(outstream); FSDirHandle *dh = FSDH_open(test_dir); CharBuf *entry = FSDH_Get_Entry(dh); while (FSDH_Next(dh)) { count++; if (CB_Equals(entry, (Obj*)foo)) { saw_foo = true; foo_was_dir = FSDH_Entry_Is_Dir(dh); } else if (CB_Equals(entry, (Obj*)boffo)) { saw_boffo = true; boffo_was_dir = FSDH_Entry_Is_Dir(dh); } } TEST_INT_EQ(batch, 2, count, "correct number of entries"); TEST_TRUE(batch, saw_foo, "Directory was iterated over"); TEST_TRUE(batch, foo_was_dir, "Dir correctly identified by Entry_Is_Dir"); TEST_TRUE(batch, saw_boffo, "File was iterated over"); TEST_FALSE(batch, boffo_was_dir, "File correctly identified by Entry_Is_Dir"); DECREF(dh); FSFolder_Delete(folder, foo_boffo); FSFolder_Delete(folder, foo); FSFolder_Delete(folder, boffo); DECREF(folder); rmdir("_fsdir_test"); }
static void test_escapes(TestBatch *batch) { CharBuf *string = CB_new(10); CharBuf *json_wanted = CB_new(10); for (int i = 0; control_escapes[i] != NULL; i++) { CB_Truncate(string, 0); CB_Cat_Char(string, i); const char *escaped = control_escapes[i]; CharBuf *json = Json_to_json((Obj*)string); CharBuf *decoded = (CharBuf*)Json_from_json(json); CB_setf(json_wanted, "\"%s\"", escaped); CB_Trim(json); TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json), "encode control escape: %s", escaped); TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded), "decode control escape: %s", escaped); DECREF(json); DECREF(decoded); } for (int i = 0; quote_escapes_source[i] != NULL; i++) { const char *source = quote_escapes_source[i]; const char *escaped = quote_escapes_json[i]; CB_setf(string, source, strlen(source)); CharBuf *json = Json_to_json((Obj*)string); CharBuf *decoded = (CharBuf*)Json_from_json(json); CB_setf(json_wanted, "\"%s\"", escaped); CB_Trim(json); TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json), "encode quote/backslash escapes: %s", source); TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded), "decode quote/backslash escapes: %s", source); DECREF(json); DECREF(decoded); } DECREF(json_wanted); DECREF(string); }
static void test_vcatf_null_obj(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar [NULL] baz"); CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %o baz", NULL); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o NULL"); DECREF(wanted); DECREF(got); }
static void test_vcatf_s(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar bizzle baz"); CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %s baz", "bizzle"); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s"); DECREF(wanted); DECREF(got); }
static void test_Truncate(TestBatch *batch) { CharBuf *wanted = CB_newf("a%s", smiley, smiley); CharBuf *got = CB_newf("a%s%sb%sc", smiley, smiley, smiley); CB_Truncate(got, 2); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Truncate"); DECREF(wanted); DECREF(got); }
static void test_serialization(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo"); CharBuf *got = (CharBuf*)TestUtils_freeze_thaw((Obj*)wanted); TEST_TRUE(batch, got && CB_Equals(wanted, (Obj*)got), "Round trip through FREEZE/THAW"); DECREF(got); DECREF(wanted); }
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; }
bool EasyAnalyzer_equals(EasyAnalyzer *self, Obj *other) { if ((EasyAnalyzer*)other == self) { return true; } if (!Obj_Is_A(other, EASYANALYZER)) { return false; } EasyAnalyzerIVARS *const ivars = EasyAnalyzer_IVARS(self); EasyAnalyzerIVARS *const ovars = EasyAnalyzer_IVARS((EasyAnalyzer*)other); if (!CB_Equals(ovars->language, (Obj*)ivars->language)) { return false; } return true; }
static void test_vcatf_u32(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar 100000 baz"); uint32_t num = 100000; CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %u32 baz", num); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u32"); DECREF(wanted); DECREF(got); }
static void test_Nip_and_Chop(TestBatch *batch) { CharBuf *wanted; CharBuf *got; wanted = CB_newf("%sb%sc", smiley, smiley); got = CB_newf("a%s%sb%sc", smiley, smiley, smiley); CB_Nip(got, 2); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Nip"); DECREF(wanted); DECREF(got); wanted = CB_newf("a%s%s", smiley, smiley); got = CB_newf("a%s%sb%sc", smiley, smiley, smiley); CB_Chop(got, 3); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Chop"); DECREF(wanted); DECREF(got); }
static void test_SubString(TestBatch *batch) { CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley); CharBuf *wanted = CB_newf("%sb%s", smiley, smiley); CharBuf *got = CB_SubString(string, 2, 3); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "SubString"); DECREF(wanted); DECREF(got); DECREF(string); }
static void test_vcatf_u64(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar 5000000000 baz"); uint64_t num = U64_C(5000000000); CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %u64 baz", num); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u64"); DECREF(wanted); DECREF(got); }
static void test_vcatf_u8(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar 3 baz"); uint8_t num = 3; CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %u8 baz", num); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u8"); DECREF(wanted); DECREF(got); }
static void test_vcatf_cb(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo bar ZEKE baz"); CharBuf *catworthy = S_get_cb("ZEKE"); CharBuf *got = S_get_cb("foo "); CB_catf(got, "bar %o baz", catworthy); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o CharBuf"); DECREF(catworthy); DECREF(wanted); DECREF(got); }
static void test_Mimic_and_Clone(TestBatch *batch) { CharBuf *wanted = S_get_cb("foo"); CharBuf *got = S_get_cb("bar"); CB_Mimic(got, (Obj*)wanted); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic"); DECREF(got); got = S_get_cb("bar"); CB_Mimic_Str(got, "foo", 3); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic_Str"); DECREF(got); got = CB_Clone(wanted); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Clone"); DECREF(got); DECREF(wanted); }
static void test_vcatf_obj(TestBatch *batch) { CharBuf *wanted = S_get_cb("ooga 20 booga"); Integer32 *i32 = Int32_new(20); CharBuf *got = S_get_cb("ooga"); CB_catf(got, " %o booga", i32); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o Obj"); DECREF(i32); DECREF(wanted); DECREF(got); }
static void test_vcatf_f64(TestBatch *batch) { CharBuf *wanted; char buf[64]; float num = 1.3f; CharBuf *got = S_get_cb("foo "); sprintf(buf, "foo bar %g baz", num); wanted = CB_new_from_trusted_utf8(buf, strlen(buf)); CB_catf(got, "bar %f64 baz", num); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%f64"); DECREF(wanted); DECREF(got); }
static void test_List(TestBatch *batch) { Folder *folder = (Folder*)RAMFolder_new(NULL); FileHandle *fh; VArray *list; CharBuf *elem; Folder_MkDir(folder, &foo); Folder_MkDir(folder, &foo_bar); Folder_MkDir(folder, &foo_bar_baz); fh = Folder_Open_FileHandle(folder, &boffo, FH_CREATE | FH_WRITE_ONLY); DECREF(fh); fh = Folder_Open_FileHandle(folder, &banana, FH_CREATE | FH_WRITE_ONLY); DECREF(fh); list = Folder_List(folder, NULL); VA_Sort(list, NULL, NULL); TEST_INT_EQ(batch, VA_Get_Size(list), 3, "List"); elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF); TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&banana), "List first file"); elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 1), CHARBUF); TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&boffo), "List second file"); elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 2), CHARBUF); TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&foo), "List dir"); DECREF(list); list = Folder_List(folder, &foo_bar); TEST_INT_EQ(batch, VA_Get_Size(list), 1, "List subdirectory contents"); elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF); TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&baz), "Just the filename"); DECREF(list); DECREF(folder); }
static void test_Is_A(TestBatch *batch) { CharBuf *charbuf = CB_new(0); VTable *bb_vtable = CB_Get_VTable(charbuf); CharBuf *klass = CB_Get_Class_Name(charbuf); TEST_TRUE(batch, CB_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf."); TEST_TRUE(batch, CB_Is_A(charbuf, OBJ), "CharBuf Is_A Obj."); TEST_TRUE(batch, bb_vtable == CHARBUF, "Get_VTable"); TEST_TRUE(batch, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass), "Get_Class_Name"); DECREF(charbuf); }
bool_t PhraseQuery_equals(PhraseQuery *self, Obj *other) { PhraseQuery *evil_twin = (PhraseQuery*)other; if (evil_twin == self) return true; if (!Obj_Is_A(other, 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; }
bool_t Tokenizer_dump_equals(Tokenizer *self, Obj *dump) { Tokenizer_dump_equals_t super_dump_equals = (Tokenizer_dump_equals_t) SUPER_METHOD(&TOKENIZER, Tokenizer, Dump_Equals); if (!super_dump_equals(self, dump)) { return false; } else { Hash *source = (Hash*)ASSERT_IS_A(dump, HASH); CharBuf *pattern = (CharBuf*)Hash_Fetch_Str(source, "pattern", 7); if (!pattern) return false; if (!CB_Equals(self->pattern, (Obj*)pattern)) return false; } return true; }
Obj* Obj_deserialize(Obj *self, InStream *instream) { CharBuf *class_name = CB_deserialize(NULL, instream); if (!self) { VTable *vtable = VTable_singleton(class_name, (VTable*)&OBJ); self = VTable_Make_Obj(vtable); } else { CharBuf *my_class = VTable_Get_Name(self->vtable); if (!CB_Equals(class_name, (Obj*)my_class)) THROW("Class mismatch: %o %o", class_name, my_class); } DECREF(class_name); return Obj_init(self); }
static void test_vcatf_x32(TestBatch *batch) { CharBuf *wanted; char buf[64]; unsigned long num = I32_MAX; CharBuf *got = S_get_cb("foo "); #if (SIZEOF_LONG == 4) sprintf(buf, "foo bar %.8lx baz", num); #elif (SIZEOF_INT == 4) sprintf(buf, "foo bar %.8x baz", (unsigned)num); #endif wanted = CB_new_from_trusted_utf8(buf, strlen(buf)); CB_catf(got, "bar %x32 baz", (uint32_t)num); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%x32"); DECREF(wanted); DECREF(got); }
void DefDelWriter_merge_segment(DefaultDeletionsWriter *self, SegReader *reader, I32Array *doc_map) { DefaultDeletionsWriterIVARS *const ivars = DefDelWriter_IVARS(self); UNUSED_VAR(doc_map); Segment *segment = SegReader_Get_Segment(reader); Hash *del_meta = (Hash*)Seg_Fetch_Metadata_Str(segment, "deletions", 9); if (del_meta) { VArray *seg_readers = ivars->seg_readers; Hash *files = (Hash*)Hash_Fetch_Str(del_meta, "files", 5); if (files) { CharBuf *seg; Hash *mini_meta; Hash_Iterate(files); while (Hash_Next(files, (Obj**)&seg, (Obj**)&mini_meta)) { /* Find the segment the deletions from the SegReader * we're adding correspond to. If it's gone, we don't * need to worry about losing deletions files that point * at it. */ for (uint32_t i = 0, max = VA_Get_Size(seg_readers); i < max; i++) { SegReader *candidate = (SegReader*)VA_Fetch(seg_readers, i); CharBuf *candidate_name = Seg_Get_Name(SegReader_Get_Segment(candidate)); if (CB_Equals(seg, (Obj*)candidate_name)) { /* If the count hasn't changed, we're about to * merge away the most recent deletions file * pointing at this target segment -- so force a * new file to be written out. */ int32_t count = (int32_t)Obj_To_I64(Hash_Fetch_Str(mini_meta, "count", 5)); DeletionsReader *del_reader = (DeletionsReader*)SegReader_Obtain( candidate, VTable_Get_Name(DELETIONSREADER)); if (count == DelReader_Del_Count(del_reader)) { ivars->updated[i] = true; } break; } } } } } }
bool_t RangeQuery_equals(RangeQuery *self, Obj *other) { RangeQuery *twin = (RangeQuery*)other; if (twin == self) { return true; } if (!Obj_Is_A(other, RANGEQUERY)) { return false; } if (self->boost != twin->boost) { return false; } if (!CB_Equals(self->field, (Obj*)twin->field)) { return false; } if (self->lower_term && !twin->lower_term) { return false; } if (self->upper_term && !twin->upper_term) { return false; } if (!self->lower_term && twin->lower_term) { return false; } if (!self->upper_term && twin->upper_term) { return false; } if (self->lower_term && !Obj_Equals(self->lower_term, twin->lower_term)) { return false; } if (self->upper_term && !Obj_Equals(self->upper_term, twin->upper_term)) { return false; } if (self->include_lower != twin->include_lower) { return false; } if (self->include_upper != twin->include_upper) { return false; } return true; }
VArray* PhraseCompiler_highlight_spans(PhraseCompiler *self, Searcher *searcher, DocVector *doc_vec, const CharBuf *field) { PhraseQuery *const parent = (PhraseQuery*)self->parent; VArray *const terms = parent->terms; VArray *const spans = VA_new(0); VArray *term_vectors; BitVector *posit_vec; BitVector *other_posit_vec; uint32_t i; const uint32_t num_terms = VA_Get_Size(terms); uint32_t num_tvs; UNUSED_VAR(searcher); // Bail if no terms or field doesn't match. if (!num_terms) { return spans; } if (!CB_Equals(field, (Obj*)parent->field)) { return spans; } term_vectors = VA_new(num_terms); posit_vec = BitVec_new(0); other_posit_vec = BitVec_new(0); for (i = 0; i < num_terms; i++) { Obj *term = VA_Fetch(terms, i); TermVector *term_vector = DocVec_Term_Vector(doc_vec, field, (CharBuf*)term); // Bail if any term is missing. if (!term_vector) break; VA_Push(term_vectors, (Obj*)term_vector); if (i == 0) { // Set initial positions from first term. uint32_t j; I32Array *positions = TV_Get_Positions(term_vector); for (j = I32Arr_Get_Size(positions); j > 0; j--) { BitVec_Set(posit_vec, I32Arr_Get(positions, j - 1)); } } else { // Filter positions using logical "and". uint32_t j; I32Array *positions = TV_Get_Positions(term_vector); BitVec_Clear_All(other_posit_vec); for (j = I32Arr_Get_Size(positions); j > 0; j--) { int32_t pos = I32Arr_Get(positions, j - 1) - i; if (pos >= 0) { BitVec_Set(other_posit_vec, pos); } } BitVec_And(posit_vec, other_posit_vec); } } // Proceed only if all terms are present. num_tvs = VA_Get_Size(term_vectors); if (num_tvs == num_terms) { TermVector *first_tv = (TermVector*)VA_Fetch(term_vectors, 0); TermVector *last_tv = (TermVector*)VA_Fetch(term_vectors, num_tvs - 1); I32Array *tv_start_positions = TV_Get_Positions(first_tv); I32Array *tv_end_positions = TV_Get_Positions(last_tv); I32Array *tv_start_offsets = TV_Get_Start_Offsets(first_tv); I32Array *tv_end_offsets = TV_Get_End_Offsets(last_tv); uint32_t terms_max = num_terms - 1; I32Array *valid_posits = BitVec_To_Array(posit_vec); uint32_t num_valid_posits = I32Arr_Get_Size(valid_posits); uint32_t j = 0; uint32_t posit_tick; float weight = PhraseCompiler_Get_Weight(self); i = 0; // Add only those starts/ends that belong to a valid position. for (posit_tick = 0; posit_tick < num_valid_posits; posit_tick++) { int32_t valid_start_posit = I32Arr_Get(valid_posits, posit_tick); int32_t valid_end_posit = valid_start_posit + terms_max; int32_t start_offset = 0, end_offset = 0; uint32_t max; for (max = I32Arr_Get_Size(tv_start_positions); i < max; i++) { if (I32Arr_Get(tv_start_positions, i) == valid_start_posit) { start_offset = I32Arr_Get(tv_start_offsets, i); break; } } for (max = I32Arr_Get_Size(tv_end_positions); j < max; j++) { if (I32Arr_Get(tv_end_positions, j) == valid_end_posit) { end_offset = I32Arr_Get(tv_end_offsets, j); break; } } VA_Push(spans, (Obj*)Span_new(start_offset, end_offset - start_offset, weight) ); i++, j++; } DECREF(valid_posits); } DECREF(other_posit_vec); DECREF(posit_vec); DECREF(term_vectors); return spans; }