Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
432 lines (281 sloc) 9.25 KB
/*
Copyright (C) 2008-2011, Parrot Foundation.
=head1 NAME
src/pmc/stringhandle.pmc - StringHandle PMC
=head1 DESCRIPTION
The StringHandle PMC performs I/O operations, but on an internal string rather
than an external file. Commonly used as a mock FileHandle for testing.
=cut
*/
#include "../src/io/io_private.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
PARROT_INLINE
static int encoding_is_utf8(PARROT_INTERP, ARGIN_NULLOK(const STRING *s))
__attribute__nonnull__(1);
#define ASSERT_ARGS_encoding_is_utf8 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/*
=head2 Internal Functions
=over 4
=item C<static int encoding_is_utf8(PARROT_INTERP, const STRING *s)>
Helper function for internal usage. Return 1 if the string argument is
not null and has utf8 encoding, 0 otherwise.
=back
=cut
*/
PARROT_INLINE
static int
encoding_is_utf8(PARROT_INTERP, ARGIN_NULLOK(const STRING *s))
{
ASSERT_ARGS(encoding_is_utf8)
if (STRING_IS_NULL(s))
return 0;
else
return STRING_equal(interp, s, CONST_STRING(interp, "utf8"));
}
pmclass StringHandle extends Handle auto_attrs {
ATTR INTVAL flags; /* Filehandle flags */
ATTR STRING *stringhandle; /* The string data */
ATTR STRING *mode; /* The mode string used in open */
ATTR STRING *filename; /* A mock path and filename */
ATTR INTVAL read_offset; /* Position, for reading bytes */
/*
=head2 Vtable Functions
=over 4
=item C<void init()>
Initializes a newly created StringHandle object.
=cut
*/
VTABLE void init() {
Parrot_StringHandle_attributes * const data_struct =
(Parrot_StringHandle_attributes *) PMC_data(SELF);
data_struct->flags = 0;
data_struct->stringhandle = NULL;
data_struct->mode = NULL;
data_struct->encoding = STRINGNULL;
data_struct->filename = NULL;
data_struct->read_offset = 0;
data_struct->io_vtable = (IO_VTABLE *)Parrot_io_get_vtable(interp,
IO_VTABLE_STRINGHANDLE, NULL);
data_struct->read_buffer = NULL;
data_struct->write_buffer = NULL;
data_struct->record_separator = CONST_STRING(interp, "\n");
PObj_custom_mark_SET(SELF);
}
/*
=item C<PMC *clone()>
Create a copy of the stringhandle.
=cut
*/
VTABLE PMC *clone() {
const Parrot_StringHandle_attributes * const old_struct = PARROT_STRINGHANDLE(SELF);
PMC * const copy = Parrot_pmc_new(INTERP, enum_class_StringHandle);
Parrot_StringHandle_attributes * const data_struct = PARROT_STRINGHANDLE(copy);
data_struct->stringhandle = old_struct->stringhandle;
data_struct->mode = old_struct->mode;
data_struct->encoding = old_struct->encoding;
data_struct->flags = old_struct->flags;
return copy;
}
/*
=item C<void mark()>
Mark active stringhandle data as live.
=cut
*/
VTABLE void mark() {
Parrot_StringHandle_attributes * const data_struct = PARROT_STRINGHANDLE(SELF);
Parrot_gc_mark_STRING_alive(INTERP, data_struct->stringhandle);
Parrot_gc_mark_STRING_alive(INTERP, data_struct->mode);
Parrot_gc_mark_STRING_alive(INTERP, data_struct->encoding);
Parrot_gc_mark_STRING_alive(INTERP, data_struct->filename);
Parrot_gc_mark_STRING_alive(INTERP, data_struct->record_separator);
Parrot_io_buffer_mark(interp, data_struct->read_buffer);
Parrot_io_buffer_mark(interp, data_struct->write_buffer);
}
/*
=item C<INTVAL get_bool()>
Returns whether the StringHandle has reached the end of the file.
=cut
*/
VTABLE INTVAL get_bool() {
STRING *stringhandle;
GET_ATTR_stringhandle(INTERP, SELF, stringhandle);
if (STRING_IS_NULL(stringhandle))
return 0;
return 1;
}
/*
=back
=head2 Methods
=over 4
=item C<METHOD open(STRING *filename :optional, STRING *mode :optional)>
Opens a string handle with the given mode. The filename is not used, but is
stored for mocking.
=cut
*/
METHOD open(STRING *filename :optional, INTVAL got_filename :opt_flag,
STRING *mode :optional, INTVAL got_mode :opt_flag) {
STRING *open_mode, *old_string;
PMC * handle;
INTVAL flags;
if (got_mode && !STRING_IS_NULL(mode))
SET_ATTR_mode(INTERP, SELF, mode);
if (got_filename && !STRING_IS_NULL(filename))
SET_ATTR_filename(INTERP, SELF, filename);
handle = Parrot_io_open(INTERP, SELF, filename, mode);
RETURN(PMC *handle);
}
/*
=item C<METHOD is_closed()>
Check if the StringHandle is open.
=cut
*/
METHOD is_closed() {
const INTVAL closed = Parrot_io_is_closed(INTERP, SELF);
RETURN(INTVAL closed);
}
/*
=item METHOD readall(STRING *name);
Read the entire contents of the StringHandle into a Parrot string. On a
StringHandle object that isn't opened yet, returns an empty string.
=cut
*/
METHOD readall(STRING *name :optional, INTVAL got_name :opt_flag) {
STRING * const string_result = Parrot_io_readall_s(INTERP, SELF);
RETURN(STRING *string_result);
}
/*
=item C<METHOD flush()>
Clear the StringHandle by resetting it to a null value.
=cut
*/
METHOD flush() {
Parrot_io_flush(INTERP, SELF);
}
/*
=item C<METHOD print([INTVAL|FLOATVAL|STRING *|PMC*] value)>
Print the passed in integer, number, string, or PMC to the stringhandle.
(Integers, numbers, and strings are auto-boxed as PMCs.)
=cut
*/
METHOD print(PMC *to_print) {
STRING * const string_to_print = VTABLE_get_string(INTERP, to_print);
Parrot_io_write_s(INTERP, SELF, string_to_print);
}
/*
=item C<METHOD puts(STRING *value)>
Print the string to the stringhandle.
=cut
*/
METHOD puts(STRING *to_print) {
const INTVAL status = Parrot_io_write_s(INTERP, SELF, to_print);
RETURN(INTVAL status);
}
/*
=item C<METHOD buffer_type(STRING *new_type :optional)>
Set or retrieve the buffering attribute for the stringhandle. This attribute is
ignored, but stored for mocking.
=cut
*/
METHOD buffer_type(STRING *new_type :optional, INTVAL got_type :opt_flag) {
INTVAL flags;
STRING * const nobuffer_string = CONST_STRING(INTERP, "unbuffered");
STRING * const linebuffer_string = CONST_STRING(INTERP, "line-buffered");
STRING * const fullbuffer_string = CONST_STRING(INTERP, "full-buffered");
GET_ATTR_flags(INTERP, SELF, flags);
if (got_type) {
if (STRING_equal(INTERP, new_type, nobuffer_string)) {
flags &= ~ PIO_BF_LINEBUF;
flags &= ~ PIO_BF_BLKBUF;
}
else if (STRING_equal(INTERP, new_type, linebuffer_string)) {
flags |= PIO_BF_LINEBUF;
flags &= ~ PIO_BF_BLKBUF;
}
else if (STRING_equal(INTERP, new_type, fullbuffer_string)) {
flags &= ~ PIO_BF_LINEBUF;
flags |= PIO_BF_BLKBUF;
}
SET_ATTR_flags(INTERP, SELF, flags);
}
if (flags & PIO_BF_LINEBUF)
RETURN(STRING *linebuffer_string);
else if (flags & PIO_BF_BLKBUF)
RETURN(STRING *fullbuffer_string);
RETURN(STRING *nobuffer_string);
}
/*
=item C<METHOD buffer_size(INTVAL new_size :optional)>
Returns the current size of the stringhandle.
=cut
*/
METHOD buffer_size(INTVAL new_size :optional, INTVAL got_size :opt_flag) {
INTVAL buffer_size;
STRING *stringhandle;
GET_ATTR_stringhandle(INTERP, SELF, stringhandle);
if (STRING_IS_NULL(stringhandle)) {
if (got_size) {
stringhandle = Parrot_str_new_noinit(interp, new_size);
SET_ATTR_stringhandle(INTERP, SELF, stringhandle);
}
else {
RETURN(INTVAL 0);
}
}
buffer_size = stringhandle->_buflen;
RETURN(INTVAL buffer_size);
}
/*
=item C<METHOD mode()>
Retrieve the read mode string for the stringhandle.
=cut
*/
METHOD mode() {
STRING *mode;
GET_ATTR_mode(INTERP, SELF, mode);
RETURN(STRING *mode);
}
/*
=item C<METHOD eof()>
Check if the StringHandle is at end-of-file (if it has read to the end of the
string data).
=cut
*/
METHOD eof() {
const INTVAL is_eof = Parrot_io_eof(INTERP, SELF);
RETURN(INTVAL 0);
}
/*
=item C<METHOD get_fd()>
StringHandles do not use integer file descriptors, so always returns an error
value.
=cut
*/
METHOD get_fd() {
UNUSED(INTERP);
RETURN(INTVAL -1);
}
/*
=item C<METHOD close()>
Close the handle.
=cut
*/
METHOD close() {
const INTVAL status = Parrot_io_close(INTERP, SELF, 0);
RETURN(INTVAL status);
}
/*
=back
=cut
*/
} /* end pmclass */
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.