use strict;
use warnings;
package KinoSearch::Store::InStream;
use base qw( KinoSearch::Util::Obj );
use KinoSearch::Util::ToolSet;
use KinoSearch::Store::FSFileDes;
use KinoSearch::Store::RAMFileDes;
1;
__END__
__XS__
MODULE = KinoSearch PACKAGE = KinoSearch::Store::InStream
kino_InStream*
reopen(self, filename, offset, len)
kino_InStream *self;
kino_ByteBuf filename;
chy_u64_t offset;
chy_u64_t len;
CODE:
RETVAL = Kino_InStream_Reopen(self, &filename, offset, len);
OUTPUT: RETVAL
kino_InStream*
new(class, file_des)
const classname_char *class;
kino_FileDes *file_des;
CODE:
CHY_UNUSED_VAR(class);
RETVAL = kino_InStream_new(file_des);
OUTPUT: RETVAL
void
sseek(self, target)
kino_InStream *self;
chy_u64_t target;
PPCODE:
Kino_InStream_SSeek(self, target);
chy_u64_t
stell(self)
kino_InStream *self;
CODE:
RETVAL = Kino_InStream_STell(self);
OUTPUT: RETVAL
chy_u64_t
slength(self)
kino_InStream *self;
CODE:
RETVAL = Kino_InStream_SLength(self);
OUTPUT: RETVAL
void
sclose(self)
kino_InStream *self;
PPCODE:
Kino_InStream_SClose(self);
void
_set_or_get(self, ...)
kino_InStream *self;
ALIAS:
get_offset = 2
get_file_des = 4
PPCODE:
{
START_SET_OR_GET_SWITCH
case 2: retval = newSVnv(self->offset);
break;
case 4: retval = kobj_to_pobj(self->file_des);
break;
END_SET_OR_GET_SWITCH
}
void
read_byteso(self, buffer_sv, start, len)
kino_InStream *self;
SV *buffer_sv;
size_t start;
size_t len;
PPCODE:
{
size_t total_len = start + len;
char *ptr;
SvUPGRADE(buffer_sv, SVt_PV);
ptr = SvGROW(buffer_sv, total_len);
Kino_InStream_Read_BytesO(self, ptr, start, len);
SvPOK_on(buffer_sv);
if (SvCUR(buffer_sv) < total_len) {
SvCUR_set(buffer_sv, total_len);
*(SvEND(buffer_sv)) = '\0';
}
}
int
read_raw_vlong(self, buffer_sv)
kino_InStream *self;
SV *buffer_sv;
CODE:
{
char *ptr;
SvUPGRADE(buffer_sv, SVt_PV);
ptr = SvGROW(buffer_sv, 10);
RETVAL = Kino_InStream_Read_Raw_VLong(self, ptr);
SvPOK_on(buffer_sv);
SvCUR_set(buffer_sv, RETVAL);
}
OUTPUT: RETVAL
=begin comment
@items = $instream->lu_read( TEMPLATE );
Read the items specified by TEMPLATE from the InStream.
=end comment
=cut
void
lu_read (self, template_sv)
kino_InStream *self;
SV *template_sv
PPCODE:
{
STRLEN tpt_len; /* bytelength of template */
char *template; /* ptr to a spot in the template */
char *tpt_end; /* ptr to the end of the template */
int repeat_count; /* number of times to repeat sym */
char sym = '\0'; /* the current symbol in the template */
IV aIV;
SV *aSV;
char aChar;
char* string;
STRLEN len;
/* prepare template string pointers */
template = SvPV(template_sv, tpt_len);
tpt_end = SvEND(template_sv);
repeat_count = 0;
while (1) {
if (repeat_count == 0) {
/* fast-forward past space characters */
while (*template == ' ' && template < tpt_end) {
template++;
}
/* break out of the loop if we've exhausted the template */
if (template == tpt_end) {
break;
}
/* derive the current symbol */
sym = *template++;
if (template == tpt_end) {
/* sym is last char in template, so process once */
repeat_count = 1;
}
else {
char countsym = *template;
if (countsym >= '0' && countsym <= '9') {
/* calculate numerical repeat count */
repeat_count = countsym - KINO_NUM_CHAR_OFFSET;
countsym = *(++template);
while ( template <= tpt_end
&& countsym >= '0'
&& countsym <= '9'
) {
repeat_count = (repeat_count * 10)
+ (countsym - KINO_NUM_CHAR_OFFSET);
countsym = *(++template);
}
}
else { /* no numeric repeat count, so process sym only once */
repeat_count = 1;
}
}
}
/* thwart potential infinite loop */
else if (repeat_count < 0) {
CONFESS( "invalid repeat_count: %d", repeat_count);
}
switch(sym) {
case 'a': /* arbitrary binary data */
len = repeat_count;
repeat_count = 1;
aSV = newSV(len + 1);
SvCUR_set(aSV, len);
SvPOK_on(aSV);
*SvEND(aSV) = '\0';
string = SvPVX(aSV);
Kino_InStream_Read_Bytes(self, string, len);
break;
case 'b': /* signed byte */
case 'B': /* unsigned byte */
aChar = Kino_InStream_Read_Byte(self);
if (sym == 'b')
aIV = aChar;
else
aIV = (chy_u8_t)aChar;
aSV = newSViv(aIV);
break;
case 'i': /* signed 32-bit integer */
aSV = newSViv( (chy_i32_t)Kino_InStream_Read_Int(self) );
break;
case 'I': /* unsigned 32-bit integer */
aSV = newSVuv( Kino_InStream_Read_Int(self) );
break;
case 'Q': /* unsigned "64-bit integer" */
aSV = newSVnv( Kino_InStream_Read_Long(self) );
break;
case 'T': /* string */
len = Kino_InStream_Read_VInt(self);
aSV = newSV(len + 1);
SvCUR_set(aSV, len);
SvPOK_on(aSV);
*SvEND(aSV) = '\0';
string = SvPVX(aSV);
Kino_InStream_Read_Bytes(self, string, len);
break;
case 'V': /* VInt */
aSV = newSVuv( Kino_InStream_Read_VInt(self) );
break;
case 'W': /* VLong */
aSV = newSVnv( Kino_InStream_Read_VLong(self) );
break;
default:
CONFESS("Invalid type in template: '%c'", sym);
aSV = Nullsv; /* unreachable; suppress compiler warning */
}
/* Put a scalar on the stack, use up one symbol or repeater */
XPUSHs( sv_2mortal(aSV) );
repeat_count -= 1;
}
}
__POD__
=begin devdocs
=head1 PRIVATE CLASS
KinoSearch::Store::InStream - Filehandles for reading invindexes.
=head1 SYNOPSIS
my $instream = $folder->open_instream( $filehandle, $offset, $length );
my @ten_vints = $instream->lu_read('V10');
=head1 DESCRIPTION
The InStream class abstracts out all input operations to KinoSearch. It is
similar to a filehandle.
Each InStream maintains its own memory buffer.
For the template used by lu_read, see InStream's companion,
L<OutStream|KinoSearch::Store::OutStream>.
=head1 COPYRIGHT
Copyright 2005-2007 Marvin Humphrey
=head1 LICENSE, DISCLAIMER, BUGS, etc.
See L<KinoSearch> version 0.20.
=end devdocs
=cut