Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: fix-socket-rea…
Fetching contributors…

Cannot retrieve contributors at this time

639 lines (498 sloc) 18.606 kB
/*
Copyright (C) 2001-2012, Parrot Foundation.
=head1 NAME
src/io/stringhandle.c - StringHandle vtables and helper routines
=head1 DESCRIPTION
The StringHandle IO_VTABLE and helper methods.
=cut
=head2 IO_VTABLE Functions
=over 4
=cut
*/
#include "parrot/parrot.h"
#include "io_private.h"
#include "pmc/pmc_stringhandle.h"
/* HEADERIZER HFILE: src/io/io_private.h */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
static void io_stringhandle_adv_position(PARROT_INTERP,
ARGMOD(PMC *handle),
size_t offset)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_close(PARROT_INTERP, ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_flush(PARROT_INTERP, ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
PARROT_CAN_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static const STR_VTABLE * io_stringhandle_get_encoding(PARROT_INTERP,
ARGIN(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static INTVAL io_stringhandle_get_flags(PARROT_INTERP, ARGIN(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static PIOHANDLE io_stringhandle_get_piohandle(PARROT_INTERP,
ARGIN(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static PIOOFF_T io_stringhandle_get_position(PARROT_INTERP,
ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_is_eof(PARROT_INTERP, ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_is_open(PARROT_INTERP, ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_open(PARROT_INTERP,
ARGMOD(PMC *handle),
ARGIN(STRING *path),
INTVAL flags,
ARGIN(STRING *mode))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(5)
FUNC_MODIFIES(*handle);
static INTVAL io_stringhandle_read_b(PARROT_INTERP,
ARGMOD(PMC *handle),
ARGOUT(char *buffer),
size_t byte_length)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*handle)
FUNC_MODIFIES(*buffer);
static PIOOFF_T io_stringhandle_seek(PARROT_INTERP,
ARGMOD(PMC *handle),
PIOOFF_T offset,
INTVAL whence)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static void io_stringhandle_set_flags(PARROT_INTERP,
ARGIN(PMC *handle),
INTVAL flags)
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static void io_stringhandle_set_position(PARROT_INTERP,
ARGMOD(PMC *handle),
PIOOFF_T pos)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static PIOOFF_T io_stringhandle_tell(PARROT_INTERP, ARGMOD(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*handle);
static size_t io_stringhandle_total_size(PARROT_INTERP, ARGIN(PMC *handle))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static INTVAL io_stringhandle_write_b(PARROT_INTERP,
ARGMOD(PMC *handle),
ARGIN(char *buffer),
size_t byte_length)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*handle);
#define ASSERT_ARGS_io_stringhandle_adv_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_close __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_flush __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_get_encoding __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_get_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_get_piohandle __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_get_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_is_eof __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_is_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle) \
, PARROT_ASSERT_ARG(path) \
, PARROT_ASSERT_ARG(mode))
#define ASSERT_ARGS_io_stringhandle_read_b __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle) \
, PARROT_ASSERT_ARG(buffer))
#define ASSERT_ARGS_io_stringhandle_seek __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_set_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_tell __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_total_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle))
#define ASSERT_ARGS_io_stringhandle_write_b __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handle) \
, PARROT_ASSERT_ARG(buffer))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/*
=item C<void io_stringhandle_setup_vtable(PARROT_INTERP, IO_VTABLE *vtable,
INTVAL idx)>
Setup the Socket IO_VTABLE
=cut
*/
void
io_stringhandle_setup_vtable(PARROT_INTERP, ARGMOD_NULLOK(IO_VTABLE *vtable), INTVAL idx)
{
ASSERT_ARGS(io_stringhandle_setup_vtable)
/* TODO: readline and other operations requiring a buffer should be able to be
done on the stringhandle memory directly to save cycles. Consider a flag
PIO_VF_CUSTOM_BUFFER and new vtables to set up a custom buffer to be used
*/
if (vtable == NULL)
vtable = IO_EDITABLE_IO_VTABLE(interp, idx);
vtable->number = idx;
vtable->flags =
PIO_VF_PATH_NOT_REQUIRED | /* StringHandle does not require a path to open */
PIO_VF_MULTI_READABLE | /* Multiple reads will not hang */
PIO_VF_AWAYS_READABLE | /* StringHandle can be read when closed or not in
read mode */
PIO_VF_SYNC_IO;
vtable->name = "StringHandle";
vtable->read_b = io_stringhandle_read_b;
vtable->write_b = io_stringhandle_write_b;
vtable->flush = io_stringhandle_flush;
vtable->is_eof = io_stringhandle_is_eof;
vtable->tell = io_stringhandle_tell;
vtable->seek = io_stringhandle_seek;
vtable->adv_position = io_stringhandle_adv_position;
vtable->set_position = io_stringhandle_set_position;
vtable->get_position = io_stringhandle_get_position;
vtable->open = io_stringhandle_open;
vtable->is_open = io_stringhandle_is_open;
vtable->close = io_stringhandle_close;
vtable->get_encoding = io_stringhandle_get_encoding;
vtable->set_flags = io_stringhandle_set_flags;
vtable->get_flags = io_stringhandle_get_flags;
vtable->total_size = io_stringhandle_total_size;
vtable->get_piohandle = io_stringhandle_get_piohandle;
}
/*
=item C<static INTVAL io_stringhandle_read_b(PARROT_INTERP, PMC *handle, char
*buffer, size_t byte_length)>
Attempt to read C<byte_length> bytes from the stringhandle.
=cut
*/
static INTVAL
io_stringhandle_read_b(PARROT_INTERP, ARGMOD(PMC *handle), ARGOUT(char *buffer), size_t byte_length)
{
ASSERT_ARGS(io_stringhandle_read_b)
INTVAL read_offs;
STRING *stringhandle;
size_t available_bytes;
GETATTR_StringHandle_read_offset(interp, handle, read_offs);
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
available_bytes = stringhandle->bufused - read_offs;
if (byte_length > available_bytes)
byte_length = available_bytes;
memcpy(buffer, (char*)stringhandle->_bufstart + read_offs, byte_length);
SETATTR_StringHandle_read_offset(interp, handle, read_offs + byte_length);
return byte_length;
}
/*
=item C<static INTVAL io_stringhandle_write_b(PARROT_INTERP, PMC *handle, char
*buffer, size_t byte_length)>
Write a number of bytes to the StringHandle.
=cut
*/
static INTVAL
io_stringhandle_write_b(PARROT_INTERP, ARGMOD(PMC *handle), ARGIN(char *buffer), size_t byte_length)
{
ASSERT_ARGS(io_stringhandle_write_b)
STRING *old_string, *new_string;
const STR_VTABLE * const encoding = io_stringhandle_get_encoding(interp, handle);
GETATTR_StringHandle_stringhandle(interp, handle, old_string);
/* TODO: Only allocate more space if we don'thave enough available already */
new_string = io_get_new_empty_string(interp, encoding, -1, old_string->bufused + byte_length);
memcpy(new_string->_bufstart, old_string->_bufstart, old_string->bufused);
memcpy(((char*)new_string->_bufstart) + old_string->bufused, buffer, byte_length);
new_string->bufused = old_string->bufused + byte_length;
STRING_scan(interp, new_string);
SETATTR_StringHandle_stringhandle(interp, handle, new_string);
return byte_length;
}
/*
=item C<static INTVAL io_stringhandle_flush(PARROT_INTERP, PMC *handle)>
Clear the StringHandle.
=cut
*/
static INTVAL
io_stringhandle_flush(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_flush)
SETATTR_StringHandle_stringhandle(interp, handle, STRINGNULL);
return 0;
}
/*
=item C<static INTVAL io_stringhandle_is_eof(PARROT_INTERP, PMC *handle)>
The StringHandle is at eof if the current read cursor is passed the end of the
string contents.
=cut
*/
static INTVAL
io_stringhandle_is_eof(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_is_eof)
INTVAL read_offs;
STRING *stringhandle;
GETATTR_StringHandle_read_offset(interp, handle, read_offs);
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
return (UINTVAL)read_offs >= stringhandle->bufused;
}
/*
=item C<static PIOOFF_T io_stringhandle_tell(PARROT_INTERP, PMC *handle)>
Get the current position of the cursor in the string.
=cut
*/
static PIOOFF_T
io_stringhandle_tell(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_tell)
INTVAL read_offset;
GETATTR_StringHandle_read_offset(interp, handle, read_offset);
return (PIOOFF_T)read_offset;
}
/*
=item C<static PIOOFF_T io_stringhandle_seek(PARROT_INTERP, PMC *handle,
PIOOFF_T offset, INTVAL whence)>
Seek to the given position in the stringhandle.
=cut
*/
static PIOOFF_T
io_stringhandle_seek(PARROT_INTERP, ARGMOD(PMC *handle), PIOOFF_T offset, INTVAL whence)
{
ASSERT_ARGS(io_stringhandle_seek)
INTVAL old_offs;
STRING *stringhandle;
INTVAL read_offs = 0;
/* TODO: Need more error checking */
switch (whence) {
case SEEK_SET:
/* Absolute seek, start from the beginning of the string */
read_offs = (INTVAL)offset;
break;
case SEEK_CUR:
/* Relative seek from the current offset */
GETATTR_StringHandle_read_offset(interp, handle, old_offs);
read_offs = (INTVAL)offset + old_offs;
break;
case SEEK_END:
/* Absolute seek backwards from the end of the buffer */
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
read_offs = (INTVAL)(stringhandle->bufused - (size_t)offset);
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
"Cannot seek with mode %d", whence);
}
SETATTR_StringHandle_read_offset(interp, handle, read_offs);
return (PIOOFF_T)read_offs;
}
/*
=item C<static void io_stringhandle_adv_position(PARROT_INTERP, PMC *handle,
size_t offset)>
Do nothing. StringHandle keeps track of position directly and doesn't need
to do it separately.
=item C<static void io_stringhandle_set_position(PARROT_INTERP, PMC *handle,
PIOOFF_T pos)>
Do nothing. StringHandle keeps track of position directly and doesn't need to
do it separately.
=item C<static PIOOFF_T io_stringhandle_get_position(PARROT_INTERP, PMC
*handle)>
Fall back to io_stringhandle_tell;
=cut
*/
static void
io_stringhandle_adv_position(PARROT_INTERP, ARGMOD(PMC *handle), size_t offset)
{
ASSERT_ARGS(io_stringhandle_adv_position)
UNUSED(handle)
UNUSED(offset)
/* StringHandle keeps track of position directly. Ignore this. */
}
static void
io_stringhandle_set_position(PARROT_INTERP, ARGMOD(PMC *handle), PIOOFF_T pos)
{
ASSERT_ARGS(io_stringhandle_set_position)
UNUSED(handle)
UNUSED(pos)
/* StringHandle keeps track of position directly. Ignore this. */
}
static PIOOFF_T
io_stringhandle_get_position(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_get_position)
return io_stringhandle_tell(interp, handle);
}
/*
=item C<static INTVAL io_stringhandle_open(PARROT_INTERP, PMC *handle, STRING
*path, INTVAL flags, STRING *mode)>
Open the StringHandle with the given mode and settings.
=cut
*/
static INTVAL
io_stringhandle_open(PARROT_INTERP, ARGMOD(PMC *handle), ARGIN(STRING *path), INTVAL flags,
ARGIN(STRING *mode))
{
ASSERT_ARGS(io_stringhandle_open)
STRING *old_handle;
GETATTR_StringHandle_stringhandle(interp, handle, old_handle);
if (STRING_IS_NULL(old_handle)) {
const STR_VTABLE * const encoding = io_stringhandle_get_encoding(interp, handle);
STRING * const new_str = io_get_new_empty_string(interp, encoding, -1, 0);
SETATTR_StringHandle_stringhandle(interp, handle, new_str);
}
SETATTR_StringHandle_flags(interp, handle, flags);
SETATTR_StringHandle_mode(interp, handle, mode);
SETATTR_StringHandle_filename(interp, handle, path);
SETATTR_StringHandle_read_offset(interp, handle, 0);
return 1;
}
/*
=item C<static INTVAL io_stringhandle_is_open(PARROT_INTERP, PMC *handle)>
Determine if the StringHandle currently thinks it is open.
=cut
*/
static INTVAL
io_stringhandle_is_open(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_is_open)
STRING *stringhandle;
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
return !STRING_IS_NULL(stringhandle);
}
/*
=item C<static INTVAL io_stringhandle_close(PARROT_INTERP, PMC *handle)>
StringHandle doesn't really close. Reset the read offset.
=cut
*/
static INTVAL
io_stringhandle_close(PARROT_INTERP, ARGMOD(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_close)
SETATTR_StringHandle_read_offset(interp, handle, 0);
return 1;
}
/*
=item C<static size_t io_stringhandle_total_size(PARROT_INTERP, PMC *handle)>
Get the total size of the contents of the StringHandle.
=cut
*/
static size_t
io_stringhandle_total_size(PARROT_INTERP, ARGIN(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_total_size)
STRING *stringhandle;
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
if (STRING_IS_NULL(stringhandle))
return 0;
return stringhandle->bufused;
}
/*
=item C<static PIOHANDLE io_stringhandle_get_piohandle(PARROT_INTERP, PMC
*handle)>
Throw an exception. StringHandle does not hold a valid PIOHANDLE.
=cut
*/
static PIOHANDLE
io_stringhandle_get_piohandle(PARROT_INTERP, ARGIN(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_get_piohandle)
const IO_VTABLE * const vtable = IO_GET_VTABLE(interp, handle);
IO_VTABLE_UNIMPLEMENTED(interp, vtable, "get_piohandle");
return PIO_INVALID_HANDLE;
}
/*
=item C<static void io_stringhandle_set_flags(PARROT_INTERP, PMC *handle, INTVAL
flags)>
Set the flags on the StringHandle.
=item C<static INTVAL io_stringhandle_get_flags(PARROT_INTERP, PMC *handle)>
Get the flags from the StringHandle.
=cut
*/
static void
io_stringhandle_set_flags(PARROT_INTERP, ARGIN(PMC *handle), INTVAL flags)
{
ASSERT_ARGS(io_stringhandle_set_flags)
PARROT_STRINGHANDLE(handle)->flags = flags;
}
static INTVAL
io_stringhandle_get_flags(PARROT_INTERP, ARGIN(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_get_flags)
return PARROT_STRINGHANDLE(handle)->flags;
}
/*
=item C<static const STR_VTABLE * io_stringhandle_get_encoding(PARROT_INTERP,
PMC *handle)>
Get the encoding from the StringHandle.
=cut
*/
PARROT_CAN_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static const STR_VTABLE *
io_stringhandle_get_encoding(PARROT_INTERP, ARGIN(PMC *handle))
{
ASSERT_ARGS(io_stringhandle_get_encoding)
/*
STRING * stringhandle;
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
if (STRING_IS_NULL(stringhandle))
return NULL;
return stringhandle->encoding;
*/
STRING *encoding_str;
GETATTR_StringHandle_encoding(interp, handle, encoding_str);
if (!STRING_IS_NULL(encoding_str))
return Parrot_find_encoding_by_string(interp, encoding_str);
return Parrot_ascii_encoding_ptr;
}
/*
=back
=cut
*/
/*
* 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.