KinoSearch1
view release on metacpan or search on metacpan
lib/KinoSearch1/Store/InStream.pm view on Meta::CPAN
__END__
__XS__
MODULE = KinoSearch1 PACKAGE = KinoSearch1::Store::InStream
=begin comment
my $instream = KinoSearch1::Store::Instream->new(
$filehandle, $offset, $length
);
Constructor. Takes 1-3 arguments, and unlike most classes in the KinoSearch1
suite, the arguments to the constructor are not labeled parameters.
The second argument, an offset, defaults to 0 if not supplied. Non-zero
offsets get factored in when calling seek and tell.
The last argument, a length, is the length of the "file" in bytes. Supplying
an explicit value is only essential for InStreams which are assigned to read a
portion of a compound file -- otherwise, the length gets auto-calculated
correctly.
=end comment
=cut
InStream*
new(class, fh_sv, ...)
char *class;
SV *fh_sv;
PREINIT:
double offset = 0;
double len = -1;
CODE:
if (items > 2) {
SV* offset_sv;
offset_sv = ST(2);
if (SvOK(offset_sv))
offset = SvNV(offset_sv);
}
if (items > 3) {
SV *len_sv;
len_sv = ST(3);
if (SvOK(len_sv))
len = SvNV(len_sv);
}
RETVAL = Kino1_InStream_new(class, fh_sv, offset, len);
OUTPUT: RETVAL
=for comment
Seek to target plus the object's start offset.
=cut
void
seek(instream, target)
InStream *instream;
double target;
PPCODE:
instream->seek(instream, target);
=for comment
Return the filehandle's position minus the offset.
=cut
double
tell(instream)
InStream *instream;
CODE:
RETVAL = instream->tell(instream);
OUTPUT: RETVAL
=for comment
Return the length of the "file" in bytes, factoring in the offset.
=cut
double
length(instream)
InStream *instream;
CODE:
RETVAL = instream->len;
OUTPUT: RETVAL
=begin comment
@items = $instream->lu_read( TEMPLATE );
Read the items specified by TEMPLATE from the InStream.
=end comment
=cut
SV*
_set_or_get(instream, ...)
InStream *instream;
ALIAS:
set_len = 1
get_len = 2
set_offset = 3
get_offset = 4
set_fh = 5
get_fh = 6
CODE:
{
KINO_START_SET_OR_GET_SWITCH
case 1: instream->len = SvNV( ST(1) );
/* fall through */
case 2: RETVAL = newSVnv(instream->len);
break;
case 3: instream->offset = SvNV( ST(1) );
/* fall through */
case 4: RETVAL = newSVnv(instream->offset);
break;
case 5: Kino1_confess("Can't set_fh");
/* fall through */
case 6: RETVAL = newSVsv(instream->fh_sv);
break;
KINO_END_SET_OR_GET_SWITCH
}
OUTPUT: RETVAL
void
lu_read (instream, template_sv)
InStream *instream;
SV *template_sv
PREINIT:
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; /* the current symbol in the template */
char countsym; /* used when calculating repeat counts */
IV aIV;
SV *aSV;
char aChar;
char* string;
STRLEN len;
PPCODE:
{
/* 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 and a possible digit repeat sym */
sym = *template++;
countsym = *template;
if (template == tpt_end) {
/* sym is last char in template, so process once */
repeat_count = 1;
}
else 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 */
if (repeat_count < 1)
Kino1_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);
string = SvPVX(aSV);
instream->read_bytes(instream, string, len);
break;
case 'b': /* signed byte */
case 'B': /* unsigned byte */
aChar = instream->read_byte(instream);
if (sym == 'b')
aIV = (signed char)aChar;
else
aIV = (unsigned char)aChar;
aSV = newSViv(aIV);
break;
case 'i': /* signed 32-bit integer */
aSV = newSViv( (I32)instream->read_int(instream) );
break;
case 'I': /* unsigned 32-bit integer */
aSV = newSVuv( instream->read_int(instream) );
break;
case 'Q': /* unsigned "64-bit integer" */
aSV = newSVnv( instream->read_long(instream) );
break;
case 'T': /* string */
len = instream->read_vint(instream);
aSV = newSV(len + 1);
SvCUR_set(aSV, len);
SvPOK_on(aSV);
string = SvPVX(aSV);
instream->read_chars(instream, string, 0, len);
break;
case 'V': /* VInt */
aSV = newSVuv( instream->read_vint(instream) );
break;
case 'W': /* VLong */
aSV = newSVnv( instream->read_vlong(instream) );
break;
default:
aSV = NULL; /* suppress unused var compiler warning */
Kino1_confess("Invalid type in template: '%c'", sym);
}
/* Put a scalar on the stack, use up one symbol or repeater */
XPUSHs( sv_2mortal(aSV) );
repeat_count -= 1;
}
}
void
DESTROY(instream)
InStream *instream;
PPCODE:
Kino1_InStream_destroy(instream);
__H__
#ifndef H_KINOSEARCH_STORE_INSTREAM
#define H_KINOSEARCH_STORE_INSTREAM 1
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "KinoSearch1UtilCarp.h"
#include "KinoSearch1UtilMathUtils.h"
/* Detect whether we're on an ASCII or EBCDIC machine. */
#if '0' == 240
#define KINO_NUM_CHAR_OFFSET 240
#else
#define KINO_NUM_CHAR_OFFSET 48
#endif
#define KINO_IO_STREAM_BUF_SIZE 1024
typedef struct instream {
PerlIO *fh;
SV *fh_sv;
double offset;
double len;
char *buf;
Off_t buf_start; /* file position of start of buffer */
int buf_len; /* number of valid bytes in the buffer */
int buf_pos; /* next byte to read */
void (*seek)(struct instream*, double);
double (*tell)(struct instream*);
char (*read_byte)(struct instream*);
void (*read_bytes)(struct instream*, char*, STRLEN);
void (*read_chars)(struct instream*, char*, STRLEN, STRLEN);
U32 (*read_int)(struct instream*);
double (*read_long)(struct instream*);
U32 (*read_vint)(struct instream*);
double (*read_vlong)(struct instream*);
} InStream;
InStream* Kino1_InStream_new (char*, SV*, double, double);
void Kino1_InStream_seek (InStream*, double);
double Kino1_InStream_tell (InStream*);
void Kino1_InStream_refill (InStream*);
char Kino1_InStream_read_byte (InStream*);
void Kino1_InStream_read_bytes (InStream*, char*, STRLEN);
void Kino1_InStream_read_chars (InStream*, char*, STRLEN, STRLEN);
U32 Kino1_InStream_read_int (InStream*);
double Kino1_InStream_read_long (InStream*);
U32 Kino1_InStream_decode_vint(char**);
U32 Kino1_InStream_read_vint (InStream*);
double Kino1_InStream_read_vlong (InStream*);
void Kino1_InStream_destroy (InStream*);
#endif /* include guard */
__C__
( run in 0.462 second using v1.01-cache-2.11-cpan-5511b514fd6 )