/*
Copyright (c) 2000-2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/


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

#include "dk.h"
#include "dkmem.h"
#include "dkstr.h"
#include "dkenc.h"
#include "dkss.h"
#include "dklog.h"
#include "dklogc.h"
#include "dksf.h"
#include "dksfc.h"
#include "dkma.h"
#include "dkstream.h"


#line 54 "testprog.ctr"


static void stream_test(void)
{
  dk_stream_t *instream, *outstream;
  char buffer[1024]; int reason;
  size_t s, x, y; int goon;
  
  instream = dkstream_openfile("testprog.o", "rb", 0, NULL);
  if(instream) { 
    reason = 0;
    outstream = dkstream_openfile("xxx.xxx", "wb", 0, &reason);
    if((!outstream) && (reason)) {
      
    }
    if(outstream) { 
      goon = 1; s = 0;
      while(goon) { 
	x = dkstream_read(instream, buffer, sizeof(buffer));
	
	if(x) {
	  y = dkstream_write(outstream, buffer, x);
	  
	  if(x != y) {
	    printf("Schreibfehler\n");
	    s += y;
	  } else {	
	    s += x;
	  }
	} else {
	  goon = 0;
	}
      }
    } else {
      printf("Failed to open outstream\n");
    }
    dkstream_close(instream); instream = NULL;
  } else {
    printf("Failed to open instream\n");
  }
  printf("%u bytes copied\n", s);
  instream = dkstream_openfile("testprog.ctr", "r", 0, NULL);
  if(instream) {
    reason = 0;
    outstream = dkstream_opengz("testprog.xxx.gz", "w", 0, &reason);
    if((!outstream) && (reason)) {
      
    }
    if(outstream) {
      while(dkstream_gets(instream, buffer, sizeof(buffer))) {
	if(!dkstream_wb_string(outstream,buffer)) {
	  printf("Schreibfehler\n");
	}
      }
      dkstream_close(outstream);
    }
    dkstream_close(instream);
  }
  instream = dkstream_opengz("testprog.xxx.gz", "r", 0, NULL);
  if(instream) {
    reason = 0;
    outstream = dkstream_openfile("testprog.xyz", "w", 0, &reason);
    if((!outstream) && (reason)) {
      
    }
    if(outstream) {
      char *xstr;
      while((xstr = dkstream_rb_string(instream)) != NULL) {
	y = strlen(xstr);
	dkstream_write(outstream, xstr, y);
	dk_delete(xstr); xstr = NULL;
      }
      dkstream_close(outstream);
    }
    dkstream_close(instream);
  }
  
}

static void exec_test(void)
{
  size_t lgt;
  char buffer[256];
  char current_dir[sizeof(buffer)];

  if(dksf_getcwd(current_dir, sizeof(current_dir))) {
    printf("Current dir %s\n", current_dir);
    lgt = sizeof(buffer);
    if(dksf_get_executable(buffer, lgt, current_dir, "tracecc", 0)) {
      printf("tracecc %s\n", buffer);
    }
    if(dksf_get_executable(buffer, lgt, current_dir, "./tracecc", 0)) {
      printf("./tracecc %s\n", buffer);
    }
    if(dksf_get_executable(buffer, lgt, current_dir, "ls", 0)) {
      printf("ls %s\n", buffer);
    }
    if(dksf_get_executable(buffer, lgt, current_dir, "openwin", 0)) {
      printf("openwin %s\n", buffer);
    }
    if(dksf_get_executable(buffer, lgt, current_dir, "autoexec", 0)) {
      printf("autoexec %s\n", buffer);
    }
    if(dksf_get_executable(buffer, lgt, current_dir, "/bin/csh", 0)) {
      printf("/bin/csh %s\n", buffer);
    }
  }

}

char p0[] = { "/" };
char p1[] = { "/usr/bin" };
char p2[] = { "../usr/bin" };
char p3[] = { "A:\\erwin\\test.dat" };
char p4[] = { "\\test.dat" };
char p5[] = { "..\\unsinn.x" };
char p6[] = { "../../../x.txt" };
char p7[] = { "dir.x" };
char p8[] = { "brabbel/sabbel/blablalba" };
char p9[] = { "erwin/../x" };

static void path_test(void)
{
  char buffer[512];
  char *pointers[] = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p9};
  int i, j;
  for(i = 0; i < 10; i++) {
    for(j = 0; j < 10; j++) {
      printf("combining %s %s\n", pointers[i], pointers[j]);
      if(dksf_path_combine(buffer, sizeof(buffer), pointers[i], pointers[j])) {
	printf("result    %s\n", buffer);
      } else {
	printf("no result\n");
      }
      printf("\n");
    }
  }
}

static void fne_test(void)
{
  dk_fne_t *fne;
  fne = dkfne_open("*.c", 1, 1);
  if(fne) {
    while(dkfne_next(fne)) {
      printf("entry %s\n", dkfne_get_fullname(fne));
      printf("short %s\n", dkfne_get_shortname(fne));
    }
    dkfne_close(fne);
  }
#if DK_HAVE_FEATURE_BACKSLASH
  fne = dkfne_open("c:\\winnt\\*.exe", 1, 1);
  if(fne) {
    while(dkfne_next(fne)) {
      printf("entry %s\n", dkfne_get_fullname(fne));
      printf("short %s\n", dkfne_get_shortname(fne));
    }
    dkfne_close(fne);
  }
#else
  fne = dkfne_open("/tmp/*ck*", 1, 1);
  if(fne) {
    while(dkfne_next(fne)) {
      printf("entry %s\n", dkfne_get_fullname(fne));
      printf("short %s\n", dkfne_get_shortname(fne));
    }
    dkfne_close(fne);
  }
#endif
  fne = dkfne_open("*.obj", 1, 0);
  if(fne) {
    printf("dkfne_open *.obj 1 0\n");
    while(dkfne_next(fne)) {
      printf("short %s\n", dkfne_get_shortname(fne));
    }
    dkfne_close(fne);
  }
  fne = dkfne_open("*.obj", 0, 1);
  if(fne) {
    printf("dkfne_open *.obj 0 1\n");
    while(dkfne_next(fne)) {
      printf("short %s\n", dkfne_get_shortname(fne));
    }
    dkfne_close(fne);
  }
}

static void dir_test(void)
{
  dk_dir_t *ptr;
  int dnt;
  printf("Testing .\n");
  ptr = dkdir_open(".");
  if(ptr) {
    while(dnt = dkdir_next(ptr)) {
      if(dnt == 1) {
#if DK_HAVE_LONG_LONG_INT
      printf("entry %llu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#else
      printf("entry %lu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#endif
      }
    }
    dkdir_close(ptr);
  }
#if DK_HAVE_FEATURE_BACKSLASH
  printf("Testing C:\\Winnt\n");
  ptr = dkdir_open("C:\\Winnt");
  if(ptr) {
    while(dnt = dkdir_next(ptr)) {
      if(dnt == 1) {
#if DK_HAVE_LONG_LONG_INT
      printf("entry %llu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#else
      printf("entry %lu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#endif
      }
    }
    dkdir_close(ptr);
  }
  printf("Testing C:\\\n");
  ptr = dkdir_open("C:\\");
  if(ptr) {
    while(dnt = dkdir_next(ptr)) {
      if(dnt == 1) {
#if DK_HAVE_LONG_LONG_INT
      printf("entry %llu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#else
      printf("entry %lu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#endif
      }
    }
    dkdir_close(ptr);
  }
#else
  printf("Testing /tmp\n");
  ptr = dkdir_open("/tmp");
  if(ptr) {
    while(dnt = dkdir_next(ptr)) {
      if(dnt == 1) {
#if DK_HAVE_LONG_LONG_INT
      printf("entry %llu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#else
      printf("entry %lu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#endif
      }
    }
    dkdir_close(ptr);
  }
  printf("Testing /\n");
  ptr = dkdir_open("/");
  if(ptr) {
    while(dnt = dkdir_next(ptr)) {
      if(dnt == 1) {
#if DK_HAVE_LONG_LONG_INT
      printf("entry %llu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#else
      printf("entry %lu %s\n", dkdir_size(ptr), dkdir_get_fullname(ptr));
#endif
      }
    }
    dkdir_close(ptr);
  }
#endif
}

static char *bool_test_strings[] = {
  "Unsinn", "Test", "01", "1", "0",
  "on", "ono", "ohno", "off", "off-line", "of",
  "t", "tr", "tru", "true", "true ", "truhe",
  "o", "ok", "okay", "y", "Y", "Yes-Sir", "YES",
  "n", "no", "no way", "f", "fa", "fal", "fals", "false",
  "falls",
  NULL
};

static void system_string_test(void)
{
  char buffer[1024];
  printf("LOGNAME: ");
  if(dksf_get_uname(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("E-NAME:  ");
  if(dksf_get_euname(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("HOME:    ");
  if(dksf_get_home(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("E-HOME:  ");
  if(dksf_get_ehome(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("TEMP:    ");
  if(dksf_get_tempdir(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("HOST:    ");
  if(dksf_get_hostname(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
  printf("DOMAIN:  ");
  if(dksf_get_domainname(buffer,sizeof(buffer))) {
    printf("%s", buffer);
  }
  printf("\n");
}


static void stat_test(void)
{
  dk_stat_t *ptr;
  char filename[] = { "/usr/local" };
  char fn2[] = { "./tracecc.cfg" };
  ptr = dkstat_open(filename);
  if(ptr) {
    printf("file: %s\n", filename);
    printf("type: %d\n", dkstat_filetype(ptr));
    printf("perm: %o\n", dkstat_permissions(ptr));
    printf("ino:  %lu\n", dkstat_inode(ptr));
    printf("dev:  %lu\n", dkstat_device(ptr));
    printf("rdev: %lu\n", dkstat_rdevice(ptr));
    printf("link: %lu\n", dkstat_nlinks(ptr));
#if DK_HAVE_LONG_LONG_INT
    printf("size: %llu\n", dkstat_size(ptr));
#else
    printf("size: %lu\n", dkstat_size(ptr));
#endif
    printf("uid:  %ld\n", dkstat_uid(ptr));
    printf("gid:  %ld\n", dkstat_gid(ptr));
    printf("ct:   %s\n", dkstat_ctime(ptr));
    printf("at:   %s\n", dkstat_atime(ptr));
    printf("mt:   %s\n", dkstat_mtime(ptr));
    dkstat_close(ptr);
  }
  ptr = dkstat_open(fn2);
  if(ptr) {
    printf("file: %s\n", fn2);
    printf("type: %d\n", dkstat_filetype(ptr));
    printf("perm: %o\n", dkstat_permissions(ptr));
    printf("ino:  %lu\n", dkstat_inode(ptr));
    printf("dev:  %lu\n", dkstat_device(ptr));
    printf("rdev: %lu\n", dkstat_rdevice(ptr));
    printf("link: %lu\n", dkstat_nlinks(ptr));
#if DK_HAVE_LONG_LONG_INT
    printf("size: %llu\n", dkstat_size(ptr));
#else
    printf("size: %lu\n", dkstat_size(ptr));
#endif
    printf("uid:  %ld\n", dkstat_uid(ptr));
    printf("gid:  %ld\n", dkstat_gid(ptr));
    printf("ct:   %s\n", dkstat_ctime(ptr));
    printf("at:   %s\n", dkstat_atime(ptr));
    printf("mt:   %s\n", dkstat_mtime(ptr));
    dkstat_close(ptr);
  }
}

static void log_test(void)
{
  char table[] = { "test" };
  char key1[] = { "/t/1" };
  char key2[] = { "/t/2" };
  char str1[] = { "Dies ist ein" };
  char str2[] = { " Test." };
  char *logmsg[6];

  logmsg[0] = str1; logmsg[1] = str2;
  dklog_msg(DK_LOG_LEVEL_INFO, logmsg, 2);
  logmsg[0] = logmsg[3] = table;
  logmsg[1] = key1; logmsg[4] = key2;
  logmsg[2] = str1; logmsg[5] = str2;
  dklog_msg_ss(DK_LOG_LEVEL_ERROR, logmsg, 2);
}

static char str1[] = { "Teststring 1" };
static char str2[] = { "Teststring 2" };

static int number = 0;

static char *string_search(void *obj, char *t, char *k, char *d)
{
  char *back;
  
  if(number++ % 2) {
    back = str1;
  } else {
    back = str2;
  }
  
  return back;
}

static dk_ss_t ss = {
  NULL,
  string_search
};

static void string_search_test(void)
{
  char *x;
  x = dkss_find("test", "test", "Dies ist ein Test\n");
  printf("%s", x);
  dkss_set_object(&ss);
  x = dkss_find("test", "test", "Dies ist ein Test\n");
  printf("%s", x);
  x = dkss_find("test", "test", "Dies ist ein Test\n");
  printf("%s", x);
  x = dkss_find("test", "test", "Dies ist ein Test\n");
  printf("%s", x);
  x = dkss_find("test", "test", "Dies ist ein Test\n");
  printf("%s", x);
}

static void encoding_test(void)
{
  printf("Encoding UL %lu %lu\n", 0x0000FFFFUL, dkenc_ntohl(0x0000FFFFUL));
  printf("Encoding US %u %u\n", 0x00FFU, dkenc_ntohl(0x00FFU));
  /*
  printf("Test UL %lu %lu\n", dkenc_ntohl(0x0000FFFFUL), ntohl(0x0000FFFFUL));
  printf("Test US %u %u\n", dkenc_ntohs(0x00FFU), ntohs(0x00FFU));
  */
}

static void string_test(void)
{
  static char str[] = { " Dies ist ein Test-String.  " };
  char *x, **ptr;
  printf("Test-String: -%s-\n", str);
  dkstr_chomp(str,NULL);
  printf("Ohne Ende:   -%s-\n", str);
  x = dkstr_start(str,NULL);
  while(x) {
    printf("Anfang:      -%s-\n", x);
    x = dkstr_next(x,NULL);
  }
  ptr = bool_test_strings;
  while(*ptr) {
    printf("%d %d %s\n",
      dkstr_is_bool(*ptr),
      dkstr_is_on(*ptr),
      *ptr
    );
    ptr++;
  }
}


static void memory_test(void)
{
  char *x; int i;
  static char buf1[] = "abcdefg";
  static char buf2[] = "abcdefg";
  static char buf3[] = "ABCDEFG";

  x = dk_new(char,512);
  if(x) {
    for(i = 0; i < 512; i++) {
      x[i] = (char)(32 + i % 52);
    }
    x[511] = (char)0;
    printf("%s\n", x);
    dk_delete(x);
  }
  printf("memcmp %s %s %d\n", buf1, buf2, dkmem_cmp(buf1,buf2,sizeof(buf1)));
  printf("memcmp %s %s %d\n", buf1, buf3, dkmem_cmp(buf1,buf3,sizeof(buf1)));
  dkmem_cpy(buf1,buf3,sizeof(buf3));
  printf("memcpy %s %s\n", buf1, buf3);
  printf("memcmp %s %s %d\n", buf1, buf3, dkmem_cmp(buf1,buf3,sizeof(buf1)));
}

static void math_test(void)
{
  long l[] = {
    -2147483647L,
    -1073741823L,
    -2L,
    -1L,
     0L,
     1L,
     2L,
     1073741823L,
     2147483647L
  };
  long ul[] = {
    4294967295UL,
    2147483649UL,
    2147483647UL,
    16UL,
    2UL,
    1UL,
    0UL
  };
  double d[] = {
    1.4e308,
    25.5,
    0.9,
    0.0,
    -0.9,
    -25.5,
    -1.4e308
  };
  int i, j, imax, jmax;
  unsigned long ulres; long lres; double dres;

  imax = jmax = sizeof(l)/sizeof(long);
  printf("Test long\n");
  for(i = 0; i < imax; i++) {
    for(j = 0; j < jmax; j++) {
      dkma_get_error(1);
      lres = dkma_add_long(l[i], l[j]);
      printf("%ld + %ld = %ld (%d)\n",
	l[i], l[j], lres, dkma_get_error(1)
      );
      dkma_get_error(1);
      lres = dkma_sub_long(l[i], l[j]);
      printf("%ld - %ld = %ld (%d)\n",
	l[i], l[j], lres, dkma_get_error(1)
      );
      dkma_get_error(1);
      lres = dkma_mul_long(l[i], l[j]);
      printf("%ld * %ld = %ld (%d)\n",
	l[i], l[j], lres, dkma_get_error(1)
      );
      dkma_get_error(1);
      lres = dkma_div_long(l[i], l[j]);
      printf("%ld / %ld = %ld (%d)\n",
	l[i], l[j], lres, dkma_get_error(1)
      );
    }
  }
  imax = jmax = sizeof(ul)/sizeof(unsigned long);
  printf("Test unsigned long\n");
  for(i = 0; i < imax; i++) {
    for(j = 0; j < jmax; j++) {
      dkma_get_error(1);
      ulres = dkma_add_ulong(ul[i], ul[j]);
      printf("%lu + %lu = %lu (%d)\n",
	ul[i], ul[j], ulres, dkma_get_error(1)
      );
      dkma_get_error(1);
      ulres = dkma_sub_ulong(ul[i], ul[j]);
      printf("%lu - %lu = %lu (%d)\n",
	ul[i], ul[j], ulres, dkma_get_error(1)
      );
      dkma_get_error(1);
      ulres = dkma_mul_ulong(ul[i], ul[j]);
      printf("%lu * %lu = %lu (%d)\n",
	ul[i], ul[j], ulres, dkma_get_error(1)
      );
      dkma_get_error(1);
      ulres = dkma_div_ulong(ul[i], ul[j]);
      printf("%lu / %lu = %lu (%d)\n",
	ul[i], ul[j], ulres, dkma_get_error(1)
      );
    }
  }
  imax = jmax = sizeof(d)/sizeof(double);
  printf("Test double\n");
  for(i = 0; i < imax; i++) {
    for(j = 0; j < jmax; j++) {
      dkma_get_error(1);
      dres = dkma_add_double(d[i], d[j]);
      
      printf("%lg + %lg = %lg (%d)\n",
	d[i], d[j], dres, dkma_get_error(1)
      );
      dkma_get_error(1);
      dres = dkma_sub_double(d[i], d[j]);
      printf("%lg - %lg = %lg (%d)\n",
	d[i], d[j], dres, dkma_get_error(1)
      );
      dkma_get_error(1);
      dres = dkma_mul_double(d[i], d[j]);
      printf("%lg * %lg = %lg (%d)\n",
	d[i], d[j], dres, dkma_get_error(1)
      );
      dkma_get_error(1);
      dres = dkma_div_double(d[i], d[j]);
      printf("%lg / %lg = %lg (%d)\n",
	d[i], d[j], dres, dkma_get_error(1)
      );
    }
  }
  printf("Test double conversions\n");
  for(i = 0; i < sizeof(d)/sizeof(double); i++) {
    dkma_get_error(1);
    lres = dkma_double_to_l(d[i]);
    printf("%lg\t%ld (%d) ", d[i], lres, dkma_get_error(1));
    ulres = dkma_double_to_ul(d[i]);
    printf("%lu (%d)\n", ulres, dkma_get_error(1));
  }
  printf("Test long conversion\n");
  for(i = 0; i < sizeof(l)/sizeof(long); i++) {
    dkma_get_error(1);
    dres = dkma_l_to_double(l[i]);
    printf("%ld %lg (%d)\n", l[i], dres, dkma_get_error(1));
  }
  printf("Test unsigned long conversion\n");
  for(i = 0; i < sizeof(ul)/sizeof(unsigned long); i++) {
    dkma_get_error(1);
    dres = dkma_ul_to_double(ul[i]);
    printf("%lu %lg (%d)\n", ul[i], dres, dkma_get_error(1));
  }
}
 
static void long_long_test(void)
{
#if DK_HAVE_LONG_LONG_INT
  long long unsigned ul[] = {
     9223372036854775808ULL,
     9223372036854775809ULL,
     9223372036854775810ULL,
    18446744073709551615ULL,
    18446744073709551614ULL,
    18446744073709551613ULL,
    23ULL
  };
  double d;
  int i;
  for(i = 0; i < (sizeof(ul)/sizeof(dk_long_long_unsigned_t)); i++) {
    printf("%20llu %-20.0lf\n", ul[i], dkma_ull_to_double(ul[i]));
  }
#else
  printf("Data type \"long long\" undefined!\n");
#endif
}

int main(int argc, char *argv[])
{
  
#line 692 "testprog.ctr"

  /* memory_test(); */
  string_test();
  /* encoding_test(); */
  /* string_search_test(); */
  /* log_test(); */
  /* stat_test(); */
  system_string_test();
  /* dir_test(); */
  /* fne_test(); */
  /* path_test(); */
  /* exec_test(); */
  /* math_test(); */
  /* stream_test(); */
  /* long_long_test(); */
  /* dktok_test(); */
  
#line 708 "testprog.ctr"

  return 0;
}


