Permalink
Switch branches/tags
Find file
Fetching contributors…
Cannot retrieve contributors at this time
284 lines (201 sloc) 6.72 KB
/*
Copyright (C) 2008-2014, Parrot Foundation.
=head1 NAME
src/pmc/handle.pmc - Handle PMC
=head1 DESCRIPTION
This is the base-class for all IO-related PMCs.
=head2 Vtable Functions
=over 4
=item C<init>
=item C<init_pmc>
Handle shouldn't be directly instantiated, init and init_pmc throws
EXCEPTION_INVALID_OPERATION.
=cut
*/
#include "parrot/parrot.h"
#include "../src/io/io_private.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass Handle provides Handle manual_attrs {
/* TODO: Consider encapsulating PIOHANDLE as a PMC type, for subclassing */
ATTR PIOHANDLE os_handle; /* Low level OS descriptor */
ATTR STRING *record_separator; /* Record separator */
ATTR IO_VTABLE *io_vtable; /* Function dispatch table */
ATTR IO_BUFFER *read_buffer; /* Read Buffer */
ATTR IO_BUFFER *write_buffer; /* Write Buffer */
ATTR STRING *encoding; /* The encoding for read/write */
VTABLE void init() :no_wb {
UNUSED(SELF)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION,
"Handle cannot be instantiated directly");
}
VTABLE void init_pmc(PMC * init) :no_wb {
UNUSED(init)
UNUSED(SELF)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION,
"Handle cannot be instantiated directly");
}
VTABLE void *get_pointer_keyed_int(INTVAL key) :no_wb {
void * ptr;
switch (key) {
case IO_PTR_IDX_VTABLE:
GET_ATTR_io_vtable(INTERP, SELF, ptr);
break;
case IO_PTR_IDX_READ_BUFFER:
GET_ATTR_read_buffer(INTERP, SELF, ptr);
break;
case IO_PTR_IDX_WRITE_BUFFER:
GET_ATTR_write_buffer(INTERP, SELF, ptr);
break;
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_PIO_ERROR,
"Handle: Cannot get pointer %d", key);
}
return ptr;
}
VTABLE void set_pointer_keyed_int(INTVAL key, void *ptr) :manual_wb {
switch (key) {
case IO_PTR_IDX_VTABLE:
{
SET_ATTR_io_vtable(INTERP, SELF, (IO_VTABLE *)ptr);
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
}
break;
case IO_PTR_IDX_READ_BUFFER:
{
SET_ATTR_read_buffer(INTERP, SELF, (IO_BUFFER *)ptr);
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
break;
}
case IO_PTR_IDX_WRITE_BUFFER:
{
SET_ATTR_write_buffer(INTERP, SELF, (IO_BUFFER *)ptr);
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
}
break;
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_PIO_ERROR,
"Handle: Cannot set pointer %d", key);
}
}
/*
=back
=head2 Methods
=over 4
=item C<METHOD isatty()>
Returns a boolean value indicating whether C<SELF> is a console/tty.
This default implementation always return false. Override it in
subtypes that are or can be tty.
=cut
*/
METHOD isatty() :no_wb {
RETURN(INTVAL 0);
}
/*
=item C<METHOD get_fd()>
Retrieve the integer file descriptor for the Handle (only available on
platforms that use integer file descriptors).
=cut
*/
METHOD get_fd() :no_wb {
PIOHANDLE os_handle;
INTVAL fd;
GET_ATTR_os_handle(INTERP, SELF, os_handle);
fd = (INTVAL)os_handle;
RETURN(INTVAL fd);
}
/*
=item C<METHOD read(INTVAL bytes)>
Read the given number of bytes from the handle and return them in a string.
=cut
*/
METHOD read(INTVAL length) :no_wb {
STRING * const string_result = Parrot_io_read_s(INTERP, SELF, length);
RETURN(STRING *string_result);
}
/*
=item C<METHOD readline()>
Read a line from the handle and return it in a string.
=cut
*/
METHOD readline(STRING * record_separator :optional, INTVAL has_rs :opt_flag) :no_wb {
STRING * string_result;
if (!has_rs) {
GET_ATTR_record_separator(interp, SELF, record_separator);
}
string_result = Parrot_io_readline_s(INTERP, SELF, record_separator);
RETURN(STRING *string_result);
}
/*
=item C<METHOD read_bytes(INTVAL bytes)>
Read the given number of bytes from the handle and return them in a
ByteBuffer. If C<bytes> is omitted, or if it's C<-1> the handle will attempt
to read whatever is available, up to the size of the buffer.
=cut
*/
METHOD read_bytes(INTVAL length :optional, INTVAL has_length :opt_flag) :no_wb {
PMC * const bb = Parrot_io_read_byte_buffer_pmc(INTERP, SELF, PMCNULL,
has_length ? length : (signed)PIO_READ_SIZE_ANY);
RETURN(PMC *bb);
}
METHOD write_bytes(PMC *bytebuffer, INTVAL length) :no_wb {
const INTVAL written = Parrot_io_write_byte_buffer_pmc(INTERP, SELF, bytebuffer, length);
RETURN(INTVAL written);
}
/*
=item C<METHOD record_separator()>
Set the record separator for readline.
=cut
*/
METHOD record_separator(STRING *str :optional, int has_str :opt_flag) {
if (has_str) {
if (STRING_IS_NULL(str))
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION,
"Record separator may not be null");
str = Parrot_io_reencode_string_for_handle(INTERP, SELF, str);
SET_ATTR_record_separator(INTERP, SELF, str);
}
else {
GET_ATTR_record_separator(INTERP, SELF, str);
}
RETURN(STRING *str);
}
/*
=item C<METHOD close()>
Close the handle.
=cut
*/
METHOD close() :no_wb {
const INTVAL status = Parrot_io_close(INTERP, SELF, 1);
RETURN(INTVAL status);
}
/*
=item C<METHOD encoding(STRING *new_encoding)>
Set or retrieve the encoding attribute (a string name of the selected encoding
scheme) for the filehandle.
=cut
*/
METHOD encoding(STRING *encoding :optional, INTVAL got_encoding :opt_flag) {
if (got_encoding) {
STRING * record_separator;
SET_ATTR_encoding(INTERP, SELF, encoding);
GET_ATTR_record_separator(INTERP, SELF, record_separator);
record_separator = Parrot_io_reencode_string_for_handle(INTERP, SELF, record_separator);
SET_ATTR_record_separator(INTERP, SELF, record_separator);
}
else {
GET_ATTR_encoding(INTERP, SELF, encoding);
}
RETURN(STRING *encoding);
}
}
/*
=back
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/