File-Raw
view release on metacpan or search on metacpan
lib/File/Raw.pm view on Meta::CPAN
=over 4
=item * macOS: Uses copyfile() for native file copying
=item * Linux: Uses sendfile() for zero-copy file transfer
=item * Linux/BSD: Uses posix_fadvise() to hint sequential reads
=back
=head2 When to use File::Raw::stat
If you need multiple attributes from a file (size, mtime, is_file, etc.),
use C<File::Raw::stat()> instead of calling individual functions:
# SLOW: 5 syscalls
my $size = File::Raw::size($path);
my $mtime = File::Raw::mtime($path);
my $is_file = File::Raw::is_file($path);
# FAST: 1 syscall
my $st = File::Raw::stat($path);
my ($size, $mtime, $is_file) = @{$st}{qw(size mtime is_file)};
=head1 XS API
File::Raw exposes a plugin C API via C<include/file_plugin.h>. Downstream
XS modules can register C-level plugins that File::Raw's read / write /
streaming dispatch routes calls into - no per-record C<call_sv>
overhead. The shared object is loaded with C<RTLD_GLOBAL> so symbols
resolve at load time without an explicit link step on Linux/macOS.
=head2 Types
=over 4
=item B<FilePluginPhase>
FILE_PLUGIN_PHASE_READ /* whole-file slurp transform */
FILE_PLUGIN_PHASE_WRITE /* whole-file spew/append transform */
FILE_PLUGIN_PHASE_RECORD /* per-record dispatch */
FILE_PLUGIN_PHASE_STREAM /* chunked feed for streaming */
=item B<FilePluginContext>
Per-call dispatch context (lifetime: single dispatch call).
typedef struct FilePluginContext {
const char *path; /* file path */
SV *data; /* read: bytes; write: payload */
SV *callback; /* per-record cb (stream phase) */
HV *options; /* per-call opts; mortal; never NULL*/
int phase;
int cancel; /* set non-zero to cancel op */
void *plugin_state; /* opaque, copied from plugin->state*/
} FilePluginContext;
=item B<FilePlugin>
Registration block; the caller owns the storage (typically a file-scope
static) and must keep it alive for as long as the plugin is registered.
typedef struct FilePlugin {
const char *name;
file_plugin_read_fn read_fn; /* NULL if not implemented */
file_plugin_write_fn write_fn;
file_plugin_record_fn record_fn;
file_plugin_stream_fn stream_fn;
void *state;
} FilePlugin;
Phase signatures:
typedef SV* (*file_plugin_read_fn) (pTHX_ FilePluginContext *ctx);
typedef SV* (*file_plugin_write_fn) (pTHX_ FilePluginContext *ctx);
typedef SV* (*file_plugin_record_fn) (pTHX_ FilePluginContext *ctx, SV *record);
typedef int (*file_plugin_stream_fn) (pTHX_ FilePluginContext *ctx,
const char *chunk, size_t len, int eof);
=back
=head2 Functions
=over 4
=item B<file_register_plugin>
int file_register_plugin(pTHX_ const FilePlugin *plugin);
Returns 1 on success, 0 if a plugin with the same name is already
registered (use C<file_unregister_plugin> first), -1 on invalid input
(NULL plugin, NULL/empty name). Call during module initialisation only
(not thread-safe).
=item B<file_unregister_plugin>
int file_unregister_plugin(pTHX_ const char *name);
Remove a plugin by name. Returns 1 if found and removed.
=item B<file_lookup_plugin>
const FilePlugin *file_lookup_plugin(pTHX_ const char *name);
Look up a plugin by name. Returns the registered struct or NULL.
=item B<file_plugin_dispatch_read> / B<file_plugin_dispatch_write> / B<file_plugin_dispatch_stream> / B<file_plugin_dispatch_record>
SV* file_plugin_dispatch_read (pTHX_ HV *opts, const char *path, SV *bytes);
SV* file_plugin_dispatch_write (pTHX_ HV *opts, const char *path, SV *payload);
SV* file_plugin_dispatch_stream(pTHX_ HV *opts, const char *path, SV *cb);
SV* file_plugin_dispatch_record(pTHX_ HV *opts, const char *path, SV *record);
Each helper extracts the C<plugin> key from C<opts>, looks up the plugin
(croaks if unknown), confirms the requested phase function pointer is
non-NULL (croaks otherwise), builds a C<FilePluginContext> on the stack,
and invokes the phase function. These are the functions File::Raw's own
XSUBs call - downstream modules normally don't need to call them
directly.
=back
( run in 3.161 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )