Home | History | Annotate | Download | only in examples
      1 /*
      2  * unbwt.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 <time.h>
     54 #include <divsufsort.h>
     55 #include "lfs.h"
     56 
     57 
     58 static
     59 size_t
     60 read_int(FILE *fp, saidx_t *n) {
     61   unsigned char c[4];
     62   size_t m = fread(c, sizeof(unsigned char), 4, fp);
     63   if(m == 4) {
     64     *n = (c[0] <<  0) | (c[1] <<  8) |
     65          (c[2] << 16) | (c[3] << 24);
     66   }
     67   return m;
     68 }
     69 
     70 static
     71 void
     72 print_help(const char *progname, int status) {
     73   fprintf(stderr,
     74           "unbwt, an inverse burrows-wheeler transform program, version %s.\n",
     75           divsufsort_version());
     76   fprintf(stderr, "usage: %s INFILE OUTFILE\n\n", progname);
     77   exit(status);
     78 }
     79 
     80 int
     81 main(int argc, const char *argv[]) {
     82   FILE *fp, *ofp;
     83   const char *fname, *ofname;
     84   sauchar_t *T;
     85   saidx_t *A;
     86   LFS_OFF_T n;
     87   size_t m;
     88   saidx_t pidx;
     89   clock_t start, finish;
     90   saint_t err, blocksize, needclose = 3;
     91 
     92   /* Check arguments. */
     93   if((argc == 1) ||
     94      (strcmp(argv[1], "-h") == 0) ||
     95      (strcmp(argv[1], "--help") == 0)) { print_help(argv[0], EXIT_SUCCESS); }
     96   if(argc != 3) { print_help(argv[0], EXIT_FAILURE); }
     97 
     98   /* Open a file for reading. */
     99   if(strcmp(argv[1], "-") != 0) {
    100 #if HAVE_FOPEN_S
    101     if(fopen_s(&fp, fname = argv[1], "rb") != 0) {
    102 #else
    103     if((fp = LFS_FOPEN(fname = argv[1], "rb")) == NULL) {
    104 #endif
    105       fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], fname);
    106       perror(NULL);
    107       exit(EXIT_FAILURE);
    108     }
    109   } else {
    110 #if HAVE__SETMODE && HAVE__FILENO
    111     if(_setmode(_fileno(stdin), _O_BINARY) == -1) {
    112       fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
    113       perror(NULL);
    114       exit(EXIT_FAILURE);
    115     }
    116 #endif
    117     fp = stdin;
    118     fname = "stdin";
    119     needclose ^= 1;
    120   }
    121 
    122   /* Open a file for writing. */
    123   if(strcmp(argv[2], "-") != 0) {
    124 #if HAVE_FOPEN_S
    125     if(fopen_s(&ofp, ofname = argv[2], "wb") != 0) {
    126 #else
    127     if((ofp = LFS_FOPEN(ofname = argv[2], "wb")) == NULL) {
    128 #endif
    129       fprintf(stderr, "%s: Cannot open file `%s': ", argv[0], ofname);
    130       perror(NULL);
    131       exit(EXIT_FAILURE);
    132     }
    133   } else {
    134 #if HAVE__SETMODE && HAVE__FILENO
    135     if(_setmode(_fileno(stdout), _O_BINARY) == -1) {
    136       fprintf(stderr, "%s: Cannot set mode: ", argv[0]);
    137       perror(NULL);
    138       exit(EXIT_FAILURE);
    139     }
    140 #endif
    141     ofp = stdout;
    142     ofname = "stdout";
    143     needclose ^= 2;
    144   }
    145 
    146   /* Read the blocksize. */
    147   if(read_int(fp, &blocksize) != 4) {
    148     fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
    149     perror(NULL);
    150     exit(EXIT_FAILURE);
    151   }
    152 
    153   /* Allocate 5blocksize bytes of memory. */
    154   T = (sauchar_t *)malloc(blocksize * sizeof(sauchar_t));
    155   A = (saidx_t *)malloc(blocksize * sizeof(saidx_t));
    156   if((T == NULL) || (A == NULL)) {
    157     fprintf(stderr, "%s: Cannot allocate memory.\n", argv[0]);
    158     exit(EXIT_FAILURE);
    159   }
    160 
    161   fprintf(stderr, "UnBWT (blocksize %" PRIdSAINT_T ") ... ", blocksize);
    162   start = clock();
    163   for(n = 0; (m = read_int(fp, &pidx)) != 0; n += m) {
    164     /* Read blocksize bytes of data. */
    165     if((m != 4) || ((m = fread(T, sizeof(sauchar_t), blocksize, fp)) == 0)) {
    166       fprintf(stderr, "%s: %s `%s': ",
    167         argv[0],
    168         (ferror(fp) || !feof(fp)) ? "Cannot read from" : "Unexpected EOF in",
    169         fname);
    170       perror(NULL);
    171       exit(EXIT_FAILURE);
    172     }
    173 
    174     /* Inverse Burrows-Wheeler Transform. */
    175     if((err = inverse_bw_transform(T, T, A, m, pidx)) != 0) {
    176       fprintf(stderr, "%s (reverseBWT): %s.\n",
    177         argv[0],
    178         (err == -1) ? "Invalid data" : "Cannot allocate memory");
    179       exit(EXIT_FAILURE);
    180     }
    181 
    182     /* Write m bytes of data. */
    183     if(fwrite(T, sizeof(sauchar_t), m, ofp) != m) {
    184       fprintf(stderr, "%s: Cannot write to `%s': ", argv[0], ofname);
    185       perror(NULL);
    186       exit(EXIT_FAILURE);
    187     }
    188   }
    189   if(ferror(fp)) {
    190     fprintf(stderr, "%s: Cannot read from `%s': ", argv[0], fname);
    191     perror(NULL);
    192     exit(EXIT_FAILURE);
    193   }
    194   finish = clock();
    195   fprintf(stderr, "%" PRIdOFF_T " bytes: %.4f sec\n",
    196     n, (double)(finish - start) / (double)CLOCKS_PER_SEC);
    197 
    198   /* Close files */
    199   if(needclose & 1) { fclose(fp); }
    200   if(needclose & 2) { fclose(ofp); }
    201 
    202   /* Deallocate memory. */
    203   free(A);
    204   free(T);
    205 
    206   return 0;
    207 }
    208