Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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");
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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);
}
Ejemplo n.º 16
0
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);
}
Ejemplo n.º 17
0
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);
}
Ejemplo n.º 18
0
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);
}
Ejemplo n.º 19
0
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);
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
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);
}
Ejemplo n.º 22
0
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);
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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);
}
Ejemplo n.º 27
0
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);
}
Ejemplo n.º 28
0
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;
                    }
                }
            }
        }
    }
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
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;
}