1/*
2 * sasearch.c for libdivsufsort
3 * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following
12 * conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#if HAVE_CONFIG_H
28# include "config.h"
29#endif
30#include <stdio.h>
31#if HAVE_STRING_H
32# include <string.h>
33#endif
34#if HAVE_STDLIB_H
35# include <stdlib.h>
36#endif
37#if HAVE_MEMORY_H
38# include <memory.h>
39#endif
40#if HAVE_STDDEF_H
41# include <stddef.h>
42#endif
43#if HAVE_STRINGS_H
44# include <strings.h>
45#endif
46#if HAVE_SYS_TYPES_H
47# include <sys/types.h>
48#endif
49#if HAVE_IO_H && HAVE_FCNTL_H
50# include <io.h>
51# include <fcntl.h>
52#endif
53#include <divsufsort.h>
54#include "lfs.h"
55
56
57static
58void
59print_help(const char *progname, int status) {
60  fprintf(stderr,
61          "sasearch, a simple SA-based full-text search tool, version %s\n",
62          divsufsort_version());
63  fprintf(stderr, "usage: %s PATTERN FILE SAFILE\n\n", progname);
64  exit(status);
65}
66
67int
68main(int argc, const char *argv[]) {
69  FILE *fp;
70  const char *P;
71  sauchar_t *T;
72  saidx_t *SA;
73  LFS_OFF_T n;
74  size_t Psize;
75  saidx_t i, size, left;
76
77  if((argc == 1) ||
78     (strcmp(argv[1], "-h") == 0) ||
79     (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
80  if(argc != 4) { print_help(argv[0], EXIT_FAILURE); }
81
82  P = argv[1];
83  Psize = strlen(P);
84
85  /* Open a file for reading. */
86#if HAVE_FOPEN_S
87  if(fopen_s(&fp, argv[2], "rb") != 0) {
88#else
89  if((fp = LFS_FOPEN(argv[2], "rb")) == NULL) {
90#endif
91    fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[2]);
92    perror(NULL);
93    exit(EXIT_FAILURE);
94  }
95
96  /* Get the file size. */
97  if(LFS_FSEEK(fp, 0, SEEK_END) == 0) {
98    n = LFS_FTELL(fp);
99    rewind(fp);
100    if(n < 0) {
101      fprintf(stderr, "%s: Cannot ftell `%s': ", argv[0], argv[2]);
102      perror(NULL);
103      exit(EXIT_FAILURE);
104    }
105  } else {
106    fprintf(stderr, "%s: Cannot fseek `%s': ", argv[0], argv[2]);
107    perror(NULL);
108    exit(EXIT_FAILURE);
109  }
110
111  /* Allocate 5n bytes of memory. */
112  T = (sauchar_t *)malloc((size_t)n * sizeof(sauchar_t));
113  SA = (saidx_t *)malloc((size_t)n * sizeof(saidx_t));
114  if((T == NULL) || (SA == NULL)) {
115    fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
116    exit(EXIT_FAILURE);
117  }
118
119  /* Read n bytes of data. */
120  if(fread(T, sizeof(sauchar_t), (size_t)n, fp) != (size_t)n) {
121    fprintf(stderr, "%s: %s `%s': ",
122      argv[0],
123      (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
124      argv[2]);
125    perror(NULL);
126    exit(EXIT_FAILURE);
127  }
128  fclose(fp);
129
130  /* Open the SA file for reading. */
131#if HAVE_FOPEN_S
132  if(fopen_s(&fp, argv[3], "rb") != 0) {
133#else
134  if((fp = LFS_FOPEN(argv[3], "rb")) == NULL) {
135#endif
136    fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], argv[3]);
137    perror(NULL);
138    exit(EXIT_FAILURE);
139  }
140
141  /* Read n * sizeof(saidx_t) bytes of data. */
142  if(fread(SA, sizeof(saidx_t), (size_t)n, fp) != (size_t)n) {
143    fprintf(stderr, "%s: %s `%s': ",
144      argv[0],
145      (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
146      argv[3]);
147    perror(NULL);
148    exit(EXIT_FAILURE);
149  }
150  fclose(fp);
151
152  /* Search and print */
153  size = sa_search(T, (saidx_t)n,
154                   (const sauchar_t *)P, (saidx_t)Psize,
155                   SA, (saidx_t)n, &left);
156  for(i = 0; i < size; ++i) {
157    fprintf(stdout, "%" PRIdSAIDX_T "\n", SA[left + i]);
158  }
159
160  /* Deallocate memory. */
161  free(SA);
162  free(T);
163
164  return 0;
165}
166