⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tail.c

📁 This is an implementation of double-array structure for representing trie, as proposed by Junichi A
💻 C
字号:
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* * tail.c - trie tail for keeping suffixes * Created: 2006-08-15 * Author:  Theppitak Karoonboonyanan <thep@linux.thai.net> */#include <string.h>#include <stdlib.h>#include <stdio.h>#include "tail.h"#include "fileutils.h"/*----------------------------------* *    INTERNAL TYPES DECLARATIONS   * *----------------------------------*//*-----------------------------------* *    PRIVATE METHODS DECLARATIONS   * *-----------------------------------*/static TrieIndex    tail_alloc_block (Tail *t);static void         tail_free_block (Tail *t, TrieIndex block);/* ==================== BEGIN IMPLEMENTATION PART ====================  *//*------------------------------------* *   INTERNAL TYPES IMPLEMENTATIONS   * *------------------------------------*//*------------------------------* *    PRIVATE DATA DEFINITONS   * *------------------------------*/typedef struct {    TrieIndex   next_free;    TrieData    data;    TrieChar   *suffix;} TailBlock;struct _Tail {    TrieIndex   num_tails;    TailBlock  *tails;    TrieIndex   first_free;    FILE       *file;    Bool        is_dirty;};/*-----------------------------* *    METHODS IMPLEMENTAIONS   * *-----------------------------*/#define TAIL_SIGNATURE      0xDFFD#define TAIL_START_BLOCKNO  1Tail *tail_open (const char *path, const char *name, TrieIOMode mode){    Tail       *t;    TrieIndex   i;    uint16      sig;    long        file_size;    t = (Tail *) malloc (sizeof (Tail));    t->file = file_open (path, name, ".tl", mode);    if (!t->file)        goto exit1;    file_size = file_length (t->file);    if (file_size != 0 && file_read_int16 (t->file, (int16 *) &sig)        && sig != TAIL_SIGNATURE)    {        goto exit2;    }    /* init tails data */    if (file_size == 0) {        t->first_free = 0;        t->num_tails  = 0;        t->tails      = NULL;        t->is_dirty   = TRUE;    } else {        file_read_int16 (t->file, &t->first_free);        file_read_int16 (t->file, &t->num_tails);        t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock));        if (!t->tails)            goto exit2;        for (i = 0; i < t->num_tails; i++) {            int8    length;            file_read_int16 (t->file, &t->tails[i].next_free);            file_read_int16 (t->file, &t->tails[i].data);            file_read_int8 (t->file, &length);            t->tails[i].suffix    = (TrieChar *) malloc (length + 1);            if (length > 0)                file_read_chars (t->file, t->tails[i].suffix, length);            t->tails[i].suffix[length] = '\0';        }        t->is_dirty = FALSE;    }    return t;exit2:    fclose (t->file);exit1:    free (t);    return NULL;}inttail_close (Tail *t){    int         ret;    TrieIndex   i;    if (0 != (ret = tail_save (t)))        return ret;    if (0 != (ret = fclose (t->file)))        return ret;    if (t->tails) {        for (i = 0; i < t->num_tails; i++)            if (t->tails[i].suffix)                free (t->tails[i].suffix);        free (t->tails);    }    free (t);    return 0;}inttail_save (Tail *t){    TrieIndex   i;    if (!t->is_dirty)        return 0;    rewind (t->file);    if (!file_write_int16 (t->file, TAIL_SIGNATURE) ||        !file_write_int16 (t->file, t->first_free)  ||        !file_write_int16 (t->file, t->num_tails))    {        return -1;    }    for (i = 0; i < t->num_tails; i++) {        int8    length;        if (!file_write_int16 (t->file, t->tails[i].next_free) ||            !file_write_int16 (t->file, t->tails[i].data))        {            return -1;        }        length = t->tails[i].suffix ? strlen (t->tails[i].suffix) : 0;        if (!file_write_int8 (t->file, length))            return -1;        if (length > 0 &&            !file_write_chars (t->file, t->tails[i].suffix, length))        {            return -1;        }    }    t->is_dirty = FALSE;    return 0;}const TrieChar *tail_get_suffix (const Tail *t, TrieIndex index){    index -= TAIL_START_BLOCKNO;    return (index < t->num_tails) ? t->tails[index].suffix : NULL;}Booltail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix){    index -= TAIL_START_BLOCKNO;    if (index < t->num_tails) {        t->tails[index].suffix = (TrieChar *) realloc (t->tails[index].suffix,                                                       strlen (suffix) + 1);        strcpy ((char *) t->tails[index].suffix, (const char *) suffix);        t->is_dirty = TRUE;        return TRUE;    }    return FALSE;}TrieIndextail_add_suffix (Tail *t, const TrieChar *suffix){    TrieIndex   new_block;    new_block = tail_alloc_block (t);    tail_set_suffix (t, new_block, suffix);    return new_block;}static TrieIndextail_alloc_block (Tail *t){    TrieIndex   block;    if (0 != t->first_free) {        block = t->first_free;        t->first_free = t->tails[block].next_free;    } else {        block = t->num_tails;        t->tails = (TailBlock *) realloc (t->tails,                                          ++t->num_tails * sizeof (TailBlock));    }    t->tails[block].next_free = -1;    t->tails[block].data = TRIE_DATA_ERROR;    t->tails[block].suffix = NULL;        return block + TAIL_START_BLOCKNO;}static voidtail_free_block (Tail *t, TrieIndex block){    TrieIndex   i, j;    block -= TAIL_START_BLOCKNO;    if (block >= t->num_tails)        return;    t->tails[block].data = TRIE_DATA_ERROR;    if (NULL != t->tails[block].suffix) {        free (t->tails[block].suffix);        t->tails[block].suffix = NULL;    }    /* find insertion point */    j = 0;    for (i = t->first_free; i != 0 && i < block; i = t->tails[i].next_free)        j = i;    /* insert free block between j and i */    t->tails[block].next_free = i;    if (0 != j)        t->tails[j].next_free = block;    else        t->first_free = block;    t->is_dirty = TRUE;}TrieDatatail_get_data (Tail *t, TrieIndex index){    index -= TAIL_START_BLOCKNO;    return (index < t->num_tails) ? t->tails[index].data : TRIE_DATA_ERROR;}Booltail_set_data (Tail *t, TrieIndex index, TrieData data){    index -= TAIL_START_BLOCKNO;    if (index < t->num_tails) {        t->tails[index].data = data;        t->is_dirty = TRUE;        return TRUE;    }    return FALSE;}voidtail_delete (Tail *t, TrieIndex index){    tail_free_block (t, index);}inttail_walk_str  (Tail            *t,                TrieIndex        s,                short           *suffix_idx,                const TrieChar  *str,                int              len){    const TrieChar *suffix;    int             i;    short           j;    suffix = tail_get_suffix (t, s);    if (!suffix)        return FALSE;    i = 0; j = *suffix_idx;    while (i < len) {        if (str[i] != suffix[j])            break;        ++i;        /* stop and stay at null-terminator */        if (0 == suffix[j])            break;        ++j;    }    *suffix_idx = j;    return i;}Booltail_walk_char (Tail            *t,                TrieIndex        s,                short           *suffix_idx,                TrieChar         c){    const TrieChar *suffix;    TrieChar        suffix_char;    suffix = tail_get_suffix (t, s);    if (!suffix)        return FALSE;    suffix_char = suffix[*suffix_idx];    if (suffix_char == c) {        if (0 != suffix_char)            ++*suffix_idx;        return TRUE;    }    return FALSE;}/*vi:ts=4:ai:expandtab*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -