/*************************************************************************************************
 * Popular encoders and decoders
 *                                                      Copyright (C) 2000-2003 Mikio Hirabayashi
 * This file is part of QDBM, Quick Database Manager.
 * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation; either version
 * 2.1 of the License or any later version.  QDBM is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
 * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA.
 *************************************************************************************************/


#include <cabin.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#undef TRUE
#define TRUE           1                 /* boolean true */
#undef FALSE
#define FALSE          0                 /* boolean false */


/* for RISC OS */
#if defined(__riscos__) || defined(__riscos)
#include <unixlib/local.h>
int __riscosify_control = __RISCOSIFY_NO_PROCESS;
#endif


/* global variables */
const char *progname;                    /* program name */


/* function prototypes */
int main(int argc, char **argv);
void usage(void);
char *readstdin(int *sp);
int runurl(int argc, char **argv);
int runbase(int argc, char **argv);
int runquote(int argc, char **argv);
int runzlib(int argc, char **argv);


/* main routine */
int main(int argc, char **argv){
  int rv;
  progname = argv[0];
  if(argc < 2) usage();
  rv = 0;
  if(!strcmp(argv[1], "url")){
    rv = runurl(argc, argv);
  } else if(!strcmp(argv[1], "base")){
    rv = runbase(argc, argv);
  } else if(!strcmp(argv[1], "quote")){
    rv = runquote(argc, argv);
  } else if(!strcmp(argv[1], "zlib")){
    rv = runzlib(argc, argv);
  } else {
    usage();
  }
  return rv;
}


/* print the usage and exit */
void usage(void){
  fprintf(stderr, "%s: popular encoders and decoders\n", progname);
  fprintf(stderr, "\n");
  fprintf(stderr, "usage:\n");
  fprintf(stderr, "  %s url [-d] [-l] [-e expr] [file]\n", progname);
  fprintf(stderr, "  %s base [-d] [-l] [-c num] [-e expr] [file]\n", progname);
  fprintf(stderr, "  %s quote [-d] [-l] [-c num] [-e expr] [file]\n", progname);
  fprintf(stderr, "  %s zlib [-d] [file]\n", progname);
  exit(1);
}


/* read the standard input */
char *readstdin(int *sp){
  char *buf;
  int i, blen, c;
  blen = 256;
  buf = cbmalloc(blen);
  for(i = 0; (c = getchar()) != EOF; i++){
    if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2);
    buf[i] = c;
  }
  buf[i] = '\0';
  *sp = i;
  return buf;
}


/* parse arguments of url command */
int runurl(int argc, char **argv){
  int i, size, dec, line;
  char *expr, *file, *buf, *res;
  dec = FALSE;
  line = FALSE;
  expr = NULL;
  file = NULL;
  for(i = 2; i < argc; i++){
    if(!file && argv[i][0] == '-'){
      if(!strcmp(argv[i], "-d")){
        dec = TRUE;
      } else if(!strcmp(argv[i], "-l")){
        line = TRUE;
      } else if(!strcmp(argv[i], "-e")){
        if(++i >= argc) usage();
        expr = argv[i];
      } else {
        usage();
      }
    } else if(!file){
      file = argv[i];
    } else {
      usage();
    }
  }
  buf = NULL;
  if(expr){
    size = strlen(expr);
    buf = cbmemdup(expr, size);
  } else if(file){
    if(!(buf = cbreadfile(file, &size))){
      fprintf(stderr, "%s: %s: cannot open\n", progname, file);
      return 1;
    }
  } else {
    buf = readstdin(&size);
  }
  if(dec){
    res = cburldecode(buf, &size);
    for(i = 0; i < size; i++){
      putchar(res[i]);
    }
    if(line) putchar('\n');
    free(res);
  } else {
    res = cburlencode(buf, size);
    for(i = 0; res[i] != '\0'; i++){
      putchar(res[i]);
    }
    free(res);
  }
  if(line) putchar('\n');
  free(buf);
  return 0;
}


/* parse arguments of base command */
int runbase(int argc, char **argv){
  int i, ci, size, dec, line, cols;
  char *expr, *file, *buf, *res;
  dec = FALSE;
  line = FALSE;
  cols = -1;
  expr = NULL;
  file = NULL;
  for(i = 2; i < argc; i++){
    if(!file && argv[i][0] == '-'){
      if(!strcmp(argv[i], "-d")){
        dec = TRUE;
      } else if(!strcmp(argv[i], "-l")){
        line = TRUE;
      } else if(!strcmp(argv[i], "-c")){
        if(++i >= argc) usage();
        cols = atoi(argv[i]);
      } else if(!strcmp(argv[i], "-e")){
        if(++i >= argc) usage();
        expr = argv[i];
      } else {
        usage();
      }
    } else if(!file){
      file = argv[i];
    } else {
      usage();
    }
  }
  buf = NULL;
  if(expr){
    size = strlen(expr);
    buf = cbmemdup(expr, size);
  } else if(file){
    if(!(buf = cbreadfile(file, &size))){
      fprintf(stderr, "%s: %s: cannot open\n", progname, file);
      return 1;
    }
  } else {
    buf = readstdin(&size);
  }
  if(dec){
    res = cbbasedecode(buf, &size);
    for(i = 0; i < size; i++){
      putchar(res[i]);
    }
    if(line) putchar('\n');
    free(res);
  } else {
    res = cbbaseencode(buf, size);
    ci = 0;
    for(i = 0; res[i] != '\0'; i++){
      if(cols > 0 && ci >= cols){
        putchar('\n');
        ci = 0;
      }
      putchar(res[i]);
      ci++;
    }
    if(line) putchar('\n');
    free(res);
  }
  free(buf);
  return 0;
}


/* parse arguments of quote command */
int runquote(int argc, char **argv){
  int i, ci, size, dec, line, cols;
  char *expr, *file, *buf, *res;
  dec = FALSE;
  line = FALSE;
  cols = -1;
  expr = NULL;
  file = NULL;
  for(i = 2; i < argc; i++){
    if(!file && argv[i][0] == '-'){
      if(!strcmp(argv[i], "-d")){
        dec = TRUE;
      } else if(!strcmp(argv[i], "-l")){
        line = TRUE;
      } else if(!strcmp(argv[i], "-c")){
        if(++i >= argc) usage();
        cols = atoi(argv[i]);
      } else if(!strcmp(argv[i], "-e")){
        if(++i >= argc) usage();
        expr = argv[i];
      } else {
        usage();
      }
    } else if(!file){
      file = argv[i];
    } else {
      usage();
    }
  }
  buf = NULL;
  if(expr){
    size = strlen(expr);
    buf = cbmemdup(expr, size);
  } else if(file){
    if(!(buf = cbreadfile(file, &size))){
      fprintf(stderr, "%s: %s: cannot open\n", progname, file);
      return 1;
    }
  } else {
    buf = readstdin(&size);
  }
  if(dec){
    res = cbquotedecode(buf, &size);
    for(i = 0; i < size; i++){
      putchar(res[i]);
    }
    if(line) putchar('\n');
    free(res);
  } else {
    res = cbquoteencode(buf, size);
    ci = 0;
    for(i = 0; res[i] != '\0'; i++){
      if(cols > 0 && (ci >= cols || (ci >= cols - 2 && res[i] == '='))){
        printf("=\n");
        ci = 0;
      }
      if(res[i] == '\r' || res[i] == '\n') ci = 0;
      putchar(res[i]);
      ci++;
    }
    if(line) putchar('\n');
    free(res);
  }
  free(buf);
  return 0;
}


/* parse arguments of zlib command */
int runzlib(int argc, char **argv){
  int i, bsiz, rsiz, dec;
  char *file, *buf, *res;
  dec = FALSE;
  file = NULL;
  for(i = 2; i < argc; i++){
    if(!file && argv[i][0] == '-'){
      if(!strcmp(argv[i], "-d")){
        dec = TRUE;
      } else {
        usage();
      }
    } else if(!file){
      file = argv[i];
    } else {
      usage();
    }
  }
  buf = NULL;
  if(file){
    if(!(buf = cbreadfile(file, &bsiz))){
      fprintf(stderr, "%s: %s: cannot open\n", progname, file);
      return 1;
    }
  } else {
    buf = readstdin(&bsiz);
  }
  if(dec){
    if(!(res = cbinflate(buf, bsiz, &rsiz))){
      fprintf(stderr, "%s: inflate failed\n", progname);
      free(buf);
      return 1;
    }
    for(i = 0; i < rsiz; i++){
      putchar(res[i]);
    }
    free(res);
  } else {
    if(!(res = cbdeflate(buf, bsiz, &rsiz))){
      fprintf(stderr, "%s: deflate failed\n", progname);
      free(buf);
      return 1;
    }
    for(i = 0; i < rsiz; i++){
      putchar(res[i]);
    }
    free(res);
  }
  free(buf);
  return 0;
}



/* END OF FILE */
