#include "apricot.h"
#ifdef PerlIO
typedef
PerlIO *FileStream;
#else
#define PERLIO_IS_STDIO 1
typedef
FILE
*FileStream;
#define PerlIO_fileno(f) fileno(f)
#endif
#include "File.h"
#include <File.inc>
#ifdef __cplusplus
extern
"C"
{
#endif
#undef my
#define inherited CComponent
#define my ((( PFile) self)-> self)
#define var (( PFile) self)
static
void
File_reset_notifications( Handle self);
void
File_init( Handle self, HV * profile)
{
SV *file;
int
fd;
dPROFILE;
var-> fd = -1;
inherited-> init( self, profile);
my-> set_mask( self, pget_i( mask));
var-> eventMask2 =
( query_method( self,
"on_read"
, 0) ? feRead : 0) |
( query_method( self,
"on_write"
, 0) ? feWrite : 0) |
( query_method( self,
"on_exception"
, 0) ? feException : 0);
File_reset_notifications( self);
fd = pget_i(fd);
if
( fd >= 0 )
my-> set_fd( self, pget_i( fd));
file = pget_sv(file);
if
( file && ( SvOK( file)))
my-> set_file( self, pget_sv( file));
CORE_INIT_TRANSIENT(File);
}
void
File_cleanup( Handle self)
{
my-> set_file( self, NULL_SV);
inherited-> cleanup( self);
}
Bool
File_is_active( Handle self, Bool autoDetach)
{
if
(var-> fd < 0)
return
false
;
if
(var->file && !IoIFP( sv_2io( var-> file))) {
if
( autoDetach)
my-> set_file( self, NULL_SV);
return
false
;
}
return
true
;
}
void
File_handle_event( Handle self, PEvent event)
{
inherited-> handle_event ( self, event);
if
( var-> stage > csNormal)
return
;
switch
( event-> cmd) {
case
cmFileRead:
my-> notify( self,
"<sS"
,
"Read"
, var-> file ? var-> file : NULL_SV);
break
;
case
cmFileWrite:
my-> notify( self,
"<sS"
,
"Write"
, var-> file ? var-> file : NULL_SV);
break
;
case
cmFileException:
my-> notify( self,
"<sS"
,
"Exception"
, var-> file ? var-> file : NULL_SV);
break
;
}
}
SV *
File_file( Handle self, Bool set, SV * file)
{
if
( !set)
return
var-> file ? newSVsv( var-> file) : NULL_SV;
if
( var-> fd >= 0) {
apc_file_detach( self);
if
( var-> file ) sv_free( var-> file);
}
var-> file = NULL;
var-> fd = -1;
if
( file && SvOK( file)) {
FileStream f = IoIFP(sv_2io(file));
if
(!f) {
warn(
"Not a IO reference passed to File::set_file"
);
}
else
{
var-> file = newSVsv( file);
var-> fd = PerlIO_fileno( f);
if
( !apc_file_attach( self)) {
sv_free( var-> file);
var-> file = NULL;
var-> fd = -1;
}
}
}
return
NULL_SV;
}
int
File_fd( Handle self, Bool set,
int
fd)
{
if
( !set)
return
var-> fd;
if
( var-> fd >= 0) {
apc_file_detach( self);
if
( var-> file ) sv_free( var-> file);
}
var-> file = NULL;
var-> fd = -1;
if
( fd >= 0 ) {
var-> fd = fd;
if
( !apc_file_attach( self))
var-> fd = -1;
}
return
var-> fd;
}
SV *
File_get_handle( Handle self)
{
char
buf[ 256];
snprintf( buf, 256,
"0x%08x"
, var-> fd);
return
newSVpv( buf, 0);
}
int
File_mask( Handle self, Bool set,
int
mask)
{
if
( !set)
return
var-> userMask;
var-> userMask = mask;
File_reset_notifications( self);
return
mask;
}
UV
File_add_notification( Handle self,
char
* name, SV * subroutine, Handle referer,
int
index)
{
UV id = inherited-> add_notification( self, name, subroutine, referer, index);
if
( id != 0) File_reset_notifications( self);
return
id;
}
void
File_remove_notification( Handle self, UV id)
{
inherited-> remove_notification( self, id);
File_reset_notifications( self);
}
static
void
File_reset_notifications( Handle self)
{
int
i, mask = var-> eventMask2;
PList list;
void
* ret[ 3];
int
cmd[ 3] = { feRead, feWrite, feException};
if
( var-> eventIDs == NULL) {
var-> eventMask = var-> eventMask2 & var-> userMask;
return
;
}
ret[0] = hash_fetch( var-> eventIDs,
"Read"
, 4);
ret[1] = hash_fetch( var-> eventIDs,
"Write"
, 5);
ret[2] = hash_fetch( var-> eventIDs,
"Exception"
, 9);
for
( i = 0; i < 3; i++) {
if
( ret[i] == NULL)
continue
;
list = var-> events + PTR2IV( ret[i]) - 1;
if
( list-> count > 0) mask |= cmd[ i];
}
mask &= var-> userMask;
if
( var-> eventMask != mask) {
var-> eventMask = mask;
if
( var-> fd >= 0)
apc_file_change_mask( self);
}
}
#ifdef __cplusplus
}
#endif