blob: 5cf09794eca167eaed01ef9817db29678ee3ae92 [file]
// Copyright 2023 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef IREE_IO_STREAM_H_
#define IREE_IO_STREAM_H_
#include <stdint.h>
#include "iree/base/api.h"
#include "iree/base/internal/atomics.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
//===----------------------------------------------------------------------===//
// iree_io_stream_t
//===----------------------------------------------------------------------===//
// Stream position; absolute or relative based on how it's used.
typedef int64_t iree_io_stream_pos_t;
// Bits defining which operations are allowed on a stream.
enum iree_io_stream_mode_bits_t {
// Allows operations that read from the stream.
IREE_IO_STREAM_MODE_READABLE = 1u << 0,
// Allows operations that write to the stream.
IREE_IO_STREAM_MODE_WRITABLE = 1u << 1,
// Allows the iree_io_stream_resize operation for extend/truncate.
IREE_IO_STREAM_MODE_RESIZABLE = 1u << 2,
// Allows the iree_io_stream_seek operation.
IREE_IO_STREAM_MODE_SEEKABLE = 1u << 3,
// Allows iree_io_stream_map_read/iree_io_stream_map_write operations.
IREE_IO_STREAM_MODE_MAPPABLE = 1u << 4,
};
typedef uint32_t iree_io_stream_mode_t;
typedef enum iree_io_stream_seek_mode_t {
// Like fseek(SEEK_SET): seek to an absolute offset in the stream.
// A value of 0 indicates start-of-stream and a value of the total stream
// length indicates end-of-stream.
IREE_IO_STREAM_SEEK_SET = 0,
// Like fseek(SEEK_CUR): seek is a relative offset from the current stream
// offset, positive or negative. A value of 0 indicates no change.
IREE_IO_STREAM_SEEK_FROM_CURRENT,
// Like fseek(SEEK_END): seek is a negative offset from the end of the stream.
// A value of 0 indicates end-of-stream (one byte past the end of the stream,
// with the offset equalling the total stream length).
//
// Example:
// 0123456789
// ^^^
// ||+- SEEK_FROM_END 0
// |+-- SEEK_FROM_END -1
// +--- SEEK_FROM_END -2
IREE_IO_STREAM_SEEK_FROM_END,
} iree_io_stream_seek_mode_t;
typedef struct iree_io_stream_t iree_io_stream_t;
// Retains the given |stream| for the caller.
IREE_API_EXPORT void iree_io_stream_retain(iree_io_stream_t* stream);
// Releases the given |stream| from the caller.
IREE_API_EXPORT void iree_io_stream_release(iree_io_stream_t* stream);
// Returns the mode of the stream indicating what operations may be performed.
IREE_API_EXPORT iree_io_stream_mode_t
iree_io_stream_mode(const iree_io_stream_t* stream);
// Returns the position of the stream relative to the stream base offset.
IREE_API_EXPORT iree_io_stream_pos_t
iree_io_stream_offset(iree_io_stream_t* stream);
// Returns the total length of the stream in bytes ignoring the current offset.
IREE_API_EXPORT iree_io_stream_pos_t
iree_io_stream_length(iree_io_stream_t* stream);
// Returns true if |stream| is positioned at the end of the stream.
// When at the end of stream reads will fail and writes will append.
IREE_API_EXPORT bool iree_io_stream_is_eos(iree_io_stream_t* stream);
// Seeks within |stream| to |seek_offset| based on the given |seek_mode|.
// If IREE_IO_STREAM_MODE_SEEKABLE is not set then only forward relative seeks
// are supported.
IREE_API_EXPORT iree_status_t iree_io_stream_seek(
iree_io_stream_t* stream, iree_io_stream_seek_mode_t seek_mode,
iree_io_stream_pos_t seek_offset);
// Seeks within |stream| to the next offset with the specified |alignment|.
// The alignment is expected to be a power-of-two value.
// No-op if the stream offset is already aligned. Valid even if
// IREE_IO_STREAM_MODE_SEEKABLE is not set as this only performs a forward
// relative seek.
IREE_API_EXPORT iree_status_t iree_io_stream_seek_to_alignment(
iree_io_stream_t* stream, iree_io_stream_pos_t alignment);
// Reads up to |buffer_capacity| bytes from |stream| into |buffer|.
// Returns the total number of bytes read in the optional |out_buffer_length|,
// which may be less than the capacity if the end of stream is reached. If
// |out_buffer_length| is not provided the read will fail if enough bytes are
// not available. Requires the stream have IREE_IO_STREAM_MODE_READABLE.
IREE_API_EXPORT iree_status_t
iree_io_stream_read(iree_io_stream_t* stream, iree_host_size_t buffer_capacity,
void* buffer, iree_host_size_t* out_buffer_length);
// Writes |buffer_length| bytes from |buffer| to |stream|.
// Requires the stream have IREE_IO_STREAM_MODE_WRITABLE.
IREE_API_EXPORT iree_status_t
iree_io_stream_write(iree_io_stream_t* stream, iree_host_size_t buffer_length,
const void* buffer);
// Writes a single character/byte to the stream.
// Requires the stream have IREE_IO_STREAM_MODE_WRITABLE.
IREE_API_EXPORT iree_status_t
iree_io_stream_write_char(iree_io_stream_t* stream, char c);
// Writes a string view to the stream (excluding NUL terminator).
// Requires the stream have IREE_IO_STREAM_MODE_WRITABLE.
IREE_API_EXPORT iree_status_t
iree_io_stream_write_string(iree_io_stream_t* stream, iree_string_view_t value);
// Writes |count| elements of |pattern_length| with the given |pattern| value.
// Requires the stream have IREE_IO_STREAM_MODE_WRITABLE.
IREE_API_EXPORT iree_status_t
iree_io_stream_fill(iree_io_stream_t* stream, iree_io_stream_pos_t count,
const void* pattern, iree_host_size_t pattern_length);
// Maps a span of |length| bytes for reading. The stream offset is advanced by
// |length| immediately and the caller can read the returned |out_span| contents
// prior to closing the file.
// Requires that IREE_IO_STREAM_MODE_READABLE and IREE_IO_STREAM_MODE_MAPPABLE
// are set.
IREE_API_EXPORT iree_status_t
iree_io_stream_map_read(iree_io_stream_t* stream, iree_host_size_t length,
iree_const_byte_span_t* out_span);
// Maps a span of |length| bytes for writing. The stream offset is advanced by
// |length| immediately and the caller must fill the returned |out_span| with
// contents prior to closing the file.
// Requires that IREE_IO_STREAM_MODE_WRITABLE and IREE_IO_STREAM_MODE_MAPPABLE
// are set.
IREE_API_EXPORT iree_status_t
iree_io_stream_map_write(iree_io_stream_t* stream, iree_host_size_t length,
iree_byte_span_t* out_span);
// Copies |length| bytes from |source_stream| to |target_stream|.
// Requires |source_stream| have IREE_IO_STREAM_MODE_READABLE and
// |target_stream| have IREE_IO_STREAM_MODE_WRITABLE.
IREE_API_EXPORT iree_status_t iree_io_stream_copy(
iree_io_stream_t* source_stream, iree_io_stream_t* target_stream,
iree_io_stream_pos_t length);
//===----------------------------------------------------------------------===//
// Lifetime management utilities
//===----------------------------------------------------------------------===//
typedef void(IREE_API_PTR* iree_io_stream_release_fn_t)(
void* user_data, iree_io_stream_t* stream);
// A callback issued when a memory stream is released.
typedef struct {
// Callback function pointer.
iree_io_stream_release_fn_t fn;
// User data passed to the callback function. Unowned.
void* user_data;
} iree_io_stream_release_callback_t;
// Returns a no-op file release callback that implies that no cleanup is
// required.
static inline iree_io_stream_release_callback_t
iree_io_stream_release_callback_null(void) {
iree_io_stream_release_callback_t callback = {NULL, NULL};
return callback;
}
//===----------------------------------------------------------------------===//
// iree_io_stream_t implementation details
//===----------------------------------------------------------------------===//
typedef struct iree_io_stream_vtable_t {
void(IREE_API_PTR* destroy)(iree_io_stream_t* IREE_RESTRICT stream);
iree_io_stream_pos_t(IREE_API_PTR* offset)(iree_io_stream_t* stream);
iree_io_stream_pos_t(IREE_API_PTR* length)(iree_io_stream_t* stream);
iree_status_t(IREE_API_PTR* seek)(iree_io_stream_t* stream,
iree_io_stream_seek_mode_t seek_mode,
iree_io_stream_pos_t seek_offset);
iree_status_t(IREE_API_PTR* read)(iree_io_stream_t* stream,
iree_host_size_t buffer_capacity,
void* buffer,
iree_host_size_t* out_buffer_length);
iree_status_t(IREE_API_PTR* write)(iree_io_stream_t* stream,
iree_host_size_t buffer_length,
const void* buffer);
iree_status_t(IREE_API_PTR* fill)(iree_io_stream_t* stream,
iree_io_stream_pos_t count,
const void* pattern,
iree_host_size_t pattern_length);
iree_status_t(IREE_API_PTR* map_read)(iree_io_stream_t* stream,
iree_host_size_t length,
iree_const_byte_span_t* out_span);
iree_status_t(IREE_API_PTR* map_write)(iree_io_stream_t* stream,
iree_host_size_t length,
iree_byte_span_t* out_span);
} iree_io_stream_vtable_t;
struct iree_io_stream_t {
iree_atomic_ref_count_t ref_count;
const iree_io_stream_vtable_t* vtable;
iree_io_stream_mode_t mode;
};
IREE_API_EXPORT void iree_io_stream_destroy(iree_io_stream_t* stream);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // IREE_IO_STREAM_H_