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 
57 static
58 void
print_help(const char * progname,int status)59 print_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 
67 int
main(int argc,const char * argv[])68 main(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