/* $Id: FileStream,v 1.10 2009/02/15 05:59:06 kiesling Exp $ -*-c-*-*/

/*
  This file is part of Ctalk.
  Copyright  2005 - 2009  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library 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 of the License, or (at your option) any later version.

  This library 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 this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

/*
 *    FileStream class.
 */

#include <stdio.h>
#include <errno.h>

Stream class FileStream;

FileStream instanceVariable streamMode Integer 0;
FileStream instanceVariable streamDev Integer 0;
FileStream instanceVariable streamRdev Integer 0;
FileStream instanceVariable streamSize LongInteger 0ll;
FileStream instanceVariable streamAtime LongInteger 0ll;
FileStream instanceVariable streamMtime LongInteger 0ll;
FileStream instanceVariable streamCtime LongInteger 0ll;
FileStream instanceVariable streamPos LongInteger 0ll;
FileStream instanceVariable streamErrno Integer 0;
FileStream instanceVariable streamPath String "";

FileStream instanceMethod statStream (void) {

  int rval;
  struct stat statbuf;
  OBJECT *self_streamMode_value_alias,
    *self_streamDev_value_alias,
    *self_streamRDev_value_alias,
    *self_streamSize_value_alias,
    *self_streamAtime_value_alias,
    *self_streamMtime_value_alias,
    *self_streamCtime_value_alias;
  char buf[MAXLABEL];
  SystemErrnoException new s;

  returnObjectClass Integer;

  if ((rval = stat (self streamPath, &statbuf)) == SUCCESS) {
    self streamMode = statbuf.st_mode;
    self streamDev = statbuf.st_dev;
    self streamRdev = statbuf.st_rdev;
    self streamSize = statbuf.st_size;
    self streamAtime = statbuf.st_atime;
    self streamMtime = statbuf.st_mtime;
    self streamCtime = statbuf.st_ctime;
  } else {
    s raiseException "FileStream : statStream: " + (self streamPath);
  }

  /*
   *  Return NULL for now, until rewritten to create an
   *  exception, and the library has a check to make sure
   *  that it discards the return value if the method is
   *  not on the right-hand side of an equation.
   */
  methodReturnNULL
}

FileStream instanceMethod size (void) {

  returnObjectClass LongInteger;

  self statStream;

  return self streamSize;
}

FileStream instanceMethod streamEof (void) {

  OBJECT *self_value;
  FILE *self_stream;
  int r;

  returnObjectClass Integer;

  self_value = self value;
  sscanf (self_value -> __o_value, "0x%p", &self_stream);

  if (feof (self_stream)) {
    return __ctalkCreateObjectInit ("result", "Integer",
 				  "Magnitude", LOCAL_VAR,
 				  "1");
  }

  return __ctalkCreateObjectInit ("result", "Integer",
 				  "Magnitude", LOCAL_VAR,
 				  "0");
}

FileStream instanceMethod = set_value (FileStream f) {

  OBJECT *f_value;

  f_value = __ctalkGetInstanceVariable (f, "value", FALSE);
  __ctalkSetObjectValue (__ctalk_self_internal () -> instancevars,
			 f_value -> __o_value);
  methodReturnSelf
}

extern int	fileno();

FileStream instanceMethod isDir (void) {
  FILE *file;
  int rval;
  struct stat statbuf;
  char buf[MAXLABEL];
  OBJECT *value_var;
  SystemErrnoException new e;

  returnObjectClass Integer;

  value_var = self value;

  sscanf (value_var -> __o_value, "0x%p", &file);
  if ((rval = fstat (fileno (file), &statbuf)) == SUCCESS) {
    sprintf (buf, "%d", S_ISDIR(statbuf.st_mode));
  } else {
    e raiseException;
    strcpy (buf, "0");
  }

  return __ctalkCreateObjectInit ("return_value", "Integer",
				  "Magnitude", LOCAL_VAR, buf);
}

FileStream instanceMethod exists (char *__path) {
  returnObjectClass Integer;
  int rval;
  struct stat statbuf;
  if ((rval = stat (__path, &statbuf)) == SUCCESS) {
    methodReturnTrue;
  } else {
    if (errno == ENOENT) {
      methodReturnFalse;
    } else {
      methodReturnTrue;
    }
  }
}
