Example #1
0
/* Reads the file from the current position to the end into a string. */
static MVMString * slurp(MVMThreadContext *tc, MVMOSHandle *h) {
    MVMIOFileData *data = (MVMIOFileData *)h->body.data;
    uv_fs_t req;
    ensure_decode_stream(tc, data);

    /* Typically we're slurping an entire file, so just request the bytes
     * until the end; repeat to ensure we get 'em all. */
    if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) < 0) {
        MVM_exception_throw_adhoc(tc, "slurp from filehandle failed: %s", uv_strerror(req.result));
    }
    /* Sometimes - usually for special files like those in /proc - the file
     * size comes up 0, even though the S_ISREG test succeeds. So in that case
     * we try a small read and switch to a "read chunks until EOF" impl.
     * Otherwise we just read the exact size of the file. */
    if (req.statbuf.st_size == 0) {
        if (read_to_buffer(tc, data, 32) > 0) {
            while (read_to_buffer(tc, data, 4096) > 0)
                ;
        }
    } else {
        while (read_to_buffer(tc, data, req.statbuf.st_size) > 0)
            ;
    }
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #2
0
MVMString * MVM_string_decodestream_get_chars(MVMThreadContext *tc, MVMDecodeStream *ds,
                                              MVMint32 chars, MVMint64 eof) {
    MVMint32 missing;

    /* If we request nothing, give empty string. */
    if (chars == 0)
        return tc->instance->str_consts.empty;

    /* If we don't already have enough chars, try and decode more. */
    missing = missing_chars(tc, ds, chars);
    ds->result_size_guess = missing;
    if (missing)
        run_decode(tc, ds, &missing, NULL, DECODE_NOT_EOF);

    /* If we've got enough, assemble a string. Otherwise, flag EOF and retry,
     * falling back to returning what's available. */
    if (missing_chars(tc, ds, chars) == 0) {
        return take_chars(tc, ds, chars, 0);
    }
    else if (eof) {
        reached_eof(tc, ds);
        return missing_chars(tc, ds, chars) == 0
            ? take_chars(tc, ds, chars, 0)
            : MVM_string_decodestream_get_all(tc, ds);
    }
    else {
        return NULL;
    }
}
Example #3
0
/* Reads the stream from the current position to the end into a string,
 * fetching as much data is available. */
MVMString * MVM_io_syncstream_slurp(MVMThreadContext *tc, MVMOSHandle *h) {
    MVMIOSyncStreamData *data = (MVMIOSyncStreamData *)h->body.data;
    ensure_decode_stream(tc, data);

    /* Fetch as much data as we can (XXX this can be more efficient, by
     * passing on down that we want to get many buffers from libuv). */
    while (read_to_buffer(tc, data, CHUNK_SIZE))
        ;
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #4
0
/* Gets the specified number of characters from the file. */
static MVMString * read_chars(MVMThreadContext *tc, MVMOSHandle *h, MVMint64 chars) {
    MVMIOFileData *data = (MVMIOFileData *)h->body.data;
    ensure_decode_stream(tc, data);

    /* Pull data until we can read the chars we want. */
    do {
        MVMString *result = MVM_string_decodestream_get_chars(tc, data->ds, chars);
        if (result != NULL)
            return result;
    } while (read_to_buffer(tc, data, CHUNK_SIZE) > 0);

    /* Reached end of file, so just take what we have. */
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #5
0
/* Reads the file from the current position to the end into a string. */
static MVMString * slurp(MVMThreadContext *tc, MVMOSHandle *h) {
    MVMIOFileData *data = (MVMIOFileData *)h->body.data;
    uv_fs_t req;
    ensure_decode_stream(tc, data);

    /* Typically we're slurping an entire file, so just request the bytes
     * until the end; repeat to ensure we get 'em all. */
    if (uv_fs_fstat(tc->loop, &req, data->fd, NULL) < 0) {
        MVM_exception_throw_adhoc(tc, "slurp from filehandle failed: %s", uv_strerror(req.result));
    }
    while (read_to_buffer(tc, data, req.statbuf.st_size) > 0)
        ;
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #6
0
/* Reads a single line from the file handle. May serve it from a buffer, if we
 * already read enough data. */
static MVMString * read_line(MVMThreadContext *tc, MVMOSHandle *h) {
    MVMIOFileData *data = (MVMIOFileData *)h->body.data;
    ensure_decode_stream(tc, data);

    /* Pull data until we can read a line. */
    do {
        MVMString *line = MVM_string_decodestream_get_until_sep(tc, data->ds, data->sep);
        if (line != NULL)
            return line;
    } while (read_to_buffer(tc, data, CHUNK_SIZE) > 0);

    /* Reached end of file, or last (non-termianted) line. */
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #7
0
/* Variant of MVM_string_decodestream_get_until_sep that is called when we
 * reach EOF. Trims the final separator if there is one, or returns the last
 * line without the EOF marker. */
MVMString * MVM_string_decodestream_get_until_sep_eof(MVMThreadContext *tc, MVMDecodeStream *ds,
                                                      MVMDecodeStreamSeparators *sep_spec, MVMint32 chomp) {
    MVMint32 sep_loc, sep_length;

    /* Decode anything remaining and flush normalization buffer. */
    reached_eof(tc, ds);

    /* Look for separator, which should by now be at the end, and chomp it
     * off if needed. */
    sep_loc = find_separator(tc, ds, sep_spec, &sep_length);
    if (sep_loc)
        return take_chars(tc, ds, sep_loc, chomp ? sep_length : 0);

    /* Otherwise, take all remaining chars. */
    return MVM_string_decodestream_get_all(tc, ds);
}
Example #8
0
/* Gets the specified number of characters from the stream. */
MVMString * MVM_io_syncstream_read_chars(MVMThreadContext *tc, MVMOSHandle *h, MVMint64 chars) {
    MVMIOSyncStreamData *data = (MVMIOSyncStreamData *)h->body.data;
    MVMString *result;
    ensure_decode_stream(tc, data);

    /* Do we already have the chars available? */
    result = MVM_string_decodestream_get_chars(tc, data->ds, chars);
    if (result) {
        return result;
    }
    else {
        /* No; read and try again. */
        read_to_buffer(tc, data, CHUNK_SIZE);
        result = MVM_string_decodestream_get_chars(tc, data->ds, chars);
        if (result != NULL)
            return result;
    }

    /* Fetched all we immediately can, so just take what we have. */
    return MVM_string_decodestream_get_all(tc, data->ds);
}
Example #9
0
/* Read handler. */
static void on_read(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) {
    ReadInfo         *ri  = (ReadInfo *)handle->data;
    MVMThreadContext *tc  = ri->tc;
    MVMObject        *arr = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTArray);
    MVMAsyncTask     *t   = (MVMAsyncTask *)MVM_repr_at_pos_o(tc,
        tc->instance->event_loop_active, ri->work_idx);
    MVM_repr_push_o(tc, arr, t->body.schedulee);
    if (nread > 0) {
        MVMROOT(tc, t, {
        MVMROOT(tc, arr, {
            /* Push the sequence number. */
            MVMObject *seq_boxed = MVM_repr_box_int(tc,
                tc->instance->boot_types.BOOTInt, ri->seq_number++);
            MVM_repr_push_o(tc, arr, seq_boxed);

            /* Either need to produce a buffer or decode characters. */
            if (ri->ds) {
                MVMString *str;
                MVMObject *boxed_str;
                MVM_string_decodestream_add_bytes(tc, ri->ds, buf->base, nread);
                str = MVM_string_decodestream_get_all(tc, ri->ds);
                boxed_str = MVM_repr_box_str(tc, tc->instance->boot_types.BOOTStr, str);
                MVM_repr_push_o(tc, arr, boxed_str);
            }
            else {
                MVMArray *res_buf      = (MVMArray *)MVM_repr_alloc_init(tc, ri->buf_type);
                res_buf->body.slots.i8 = buf->base;
                res_buf->body.start    = 0;
                res_buf->body.ssize    = nread;
                res_buf->body.elems    = nread;
                MVM_repr_push_o(tc, arr, (MVMObject *)res_buf);
            }

            /* Finally, no error. */
            MVM_repr_push_o(tc, arr, tc->instance->boot_types.BOOTStr);
        });
        });