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

📄 index.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.     Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include "posix.h"#include "lib.h"#include "cset.h"#include "cmap.h"#include "errarg.h"#include "error.h"#include "refid.h"#include "search.h"#include "index.h"#include "defs.h"// Interface to mmap.extern "C" {  void *mapread(int fd, int len);  int unmap(void *, int len);}const int minus_one = -1;int verify_flag = 0;struct word_list;class index_search_item : public search_item {  search_item *out_of_date_files;  index_header header;  char *buffer;  void *map_addr;  int map_len;  tag *tags;  int *table;  int *lists;  char *pool;  char *key_buffer;  char *filename_buffer;  int filename_buflen;  char **common_words_table;  int common_words_table_size;  const char *ignore_fields;  time_t mtime;  const char *do_verify();  const int *search1(const char **pp, const char *end);  const int *search(const char *ptr, int length, int **temp_listp);  const char *munge_filename(const char *);  void read_common_words_file();  void add_out_of_date_file(int fd, const char *filename, int fid);public:  index_search_item(const char *, int);  ~index_search_item();  int load(int fd);  search_item_iterator *make_search_item_iterator(const char *);  int verify();  void check_files();  int next_filename_id() const;  friend class index_search_item_iterator;};class index_search_item_iterator : public search_item_iterator {  index_search_item *indx;  search_item_iterator *out_of_date_files_iter;  search_item *next_out_of_date_file;  const int *found_list;  int *temp_list;  char *buf;  int buflen;  linear_searcher searcher;  char *query;  int get_tag(int tagno, const linear_searcher &, const char **, int *,	      reference_id *);public:  index_search_item_iterator(index_search_item *, const char *);  ~index_search_item_iterator();  int next(const linear_searcher &, const char **, int *, reference_id *);};index_search_item::index_search_item(const char *filename, int fid): search_item(filename, fid), out_of_date_files(0), key_buffer(0),  filename_buffer(0), filename_buflen(0), common_words_table(0),  map_addr(0), map_len(0), buffer(0){}index_search_item::~index_search_item(){  if (buffer)    free(buffer);  if (map_addr) {    if (unmap(map_addr, map_len) < 0)      error("unmap: %1", strerror(errno));  }  while (out_of_date_files) {    search_item *tem = out_of_date_files;    out_of_date_files = out_of_date_files->next;    delete tem;  }  a_delete filename_buffer;  a_delete key_buffer;  if (common_words_table) {    for (int i = 0; i < common_words_table_size; i++)      a_delete common_words_table[i];    a_delete common_words_table;  }}class file_closer {  int *fdp;public:  file_closer(int &fd) : fdp(&fd) { }  ~file_closer() { close(*fdp); }};  int index_search_item::load(int fd){  file_closer fd_closer(fd);	// close fd on return  struct stat sb;  if (fstat(fd, &sb) < 0) {    error("can't fstat `%1': %2", name, strerror(errno));    return 0;  }  if (!S_ISREG(sb.st_mode)) {    error("`%1' is not a regular file", name);    return 0;  }  mtime = sb.st_mtime;  int size = int(sb.st_size);  char *addr;  map_addr = mapread(fd, size);  if (map_addr) {    addr = (char *)map_addr;    map_len = size;  }  else {    addr = buffer = (char *)malloc(size);    if (buffer == 0) {      error("can't allocate buffer for `%1'", name);      return 0;    }    char *ptr = buffer;    int bytes_to_read = size;    while (bytes_to_read > 0) {      int nread = read(fd, ptr, bytes_to_read);      if (nread == 0) {	error("unexpected EOF on `%1'", name);	return 0;      }      if (nread < 0) {	error("read error on `%1': %2", name, strerror(errno));	return 0;      }      bytes_to_read -= nread;      ptr += nread;    }  }  header = *(index_header *)addr;  if (header.magic != INDEX_MAGIC) {    error("`%1' is not an index file: wrong magic number", name);    return 0;  }  if (header.version != INDEX_VERSION) {    error("version number in `%1' is wrong: was %2, should be %3",	  name, header.version, INDEX_VERSION);    return 0;  }  int sz = (header.tags_size * sizeof(tag)	    + header.lists_size * sizeof(int)	    + header.table_size * sizeof(int)	    + header.strings_size	    + sizeof(header));  if (sz != size) {    error("size of `%1' is wrong: was %2, should be %3",	  name, size, sz);    return 0;  }  tags = (tag *)(addr + sizeof(header));  lists = (int *)(tags + header.tags_size);  table = (int *)(lists + header.lists_size);  pool = (char *)(table + header.table_size);  ignore_fields = strchr(strchr(pool, '\0') + 1, '\0') + 1;  key_buffer = new char[header.truncate];  read_common_words_file();  return 1;}const char *index_search_item::do_verify(){  if (tags == 0)    return "not loaded";  if (lists[header.lists_size - 1] >= 0)    return "last list element not negative";  int i;  for (i = 0; i < header.table_size; i++) {    int li = table[i];    if (li >= header.lists_size)      return "bad list index";    if (li >= 0) {      for (int *ptr = lists + li; *ptr >= 0; ptr++) {	if (*ptr >= header.tags_size)	  return "bad tag index";	if (*ptr >= ptr[1] && ptr[1] >= 0)	  return "list not ordered";      }    }  }  for (i = 0; i < header.tags_size; i++) {    if (tags[i].filename_index >= header.strings_size)      return "bad index in tags";    if (tags[i].length < 0)      return "bad length in tags";    if (tags[i].start < 0)      return "bad start in tags";  }  if (pool[header.strings_size - 1] != '\0')    return "last character in pool not nul";  return 0;}int index_search_item::verify(){  const char *reason = do_verify();  if (!reason)    return 1;  error("`%1' is bad: %2", name, reason);  return 0;}int index_search_item::next_filename_id() const{  return filename_id + header.strings_size + 1;}search_item_iterator *index_search_item::make_search_item_iterator(  const char *query){  return new index_search_item_iterator(this, query);}search_item *make_index_search_item(const char *filename, int fid){  char *index_filename = new char[strlen(filename) + sizeof(INDEX_SUFFIX)];  strcpy(index_filename, filename);  strcat(index_filename, INDEX_SUFFIX);  int fd = open(index_filename, O_RDONLY);  if (fd < 0)    return 0;  index_search_item *item = new index_search_item(index_filename, fid);  a_delete index_filename;  if (!item->load(fd)) {    close(fd);    delete item;    return 0;  }  else if (verify_flag && !item->verify()) {    delete item;    return 0;  }  else {    item->check_files();    return item;  }}index_search_item_iterator::index_search_item_iterator(index_search_item *ind,						       const char *q): indx(ind), buf(0), buflen(0), temp_list(0), query(strsave(q)),  searcher(q, strlen(q), ind->ignore_fields, ind->header.truncate),  out_of_date_files_iter(0), next_out_of_date_file(0){  found_list = indx->search(q, strlen(q), &temp_list);  if (!found_list) {    found_list = &minus_one;    warning("all keys would have been discarded in constructing index `%1'",	    indx->name);  }}index_search_item_iterator::~index_search_item_iterator(){  a_delete temp_list;  a_delete buf;

⌨️ 快捷键说明

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