📄 instream.pm
字号:
package KinoSearch::Store::InStream;use base qw( KinoSearch::Util::CClass );use strict;use warnings;use KinoSearch::Util::ToolSet;sub close { CORE::close shift->get_fh }=for commentDupe the filehandle and create a new object around the dupe. Seek the dupeto the same spot as the original.=cutsub clone_stream { my $self = shift; open( my $duped_fh, '<&=', $self->get_fh ) or confess("Couldn't dupe filehandle: $!"); my $evil_twin = __PACKAGE__->new( $duped_fh, $self->get_offset, $self->length, ); $evil_twin->seek( $self->tell ); return $evil_twin;}1;__END____XS__MODULE = KinoSearch PACKAGE = KinoSearch::Store::InStream=begin comment my $instream = KinoSearch::Store::Instream->new( $filehandle, $offset, $length );Constructor. Takes 1-3 arguments, and unlike most classes in the KinoSearchsuite, the arguments to the constructor are not labeled parameters.The second argument, an offset, defaults to 0 if not supplied. Non-zerooffsets get factored in when calling seek and tell.The last argument, a length, is the length of the "file" in bytes. Supplyingan explicit value is only essential for InStreams which are assigned to read aportion of a compound file -- otherwise, the length gets auto-calculatedcorrectly.=end comment=cutInStream*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 = Kino_InStream_new(class, fh_sv, offset, len);OUTPUT: RETVAL=for commentSeek to target plus the object's start offset.=cutvoidseek(instream, target) InStream *instream; double target;PPCODE: instream->seek(instream, target);=for commentReturn the filehandle's position minus the offset.=cutdoubletell(instream) InStream *instream;CODE: RETVAL = instream->tell(instream);OUTPUT: RETVAL=for commentReturn the length of the "file" in bytes, factoring in the offset.=cutdoublelength(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=cutSV*_set_or_get(instream, ...) InStream *instream;ALIAS: set_len = 1 get_len = 2 set_offset = 3 get_offset = 4 set_fh = 5 get_fh = 6CODE:{ 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: Kino_confess("Can't set_fh"); /* fall through */ case 6: RETVAL = newSVsv(instream->fh_sv); break; KINO_END_SET_OR_GET_SWITCH}OUTPUT: RETVALvoidlu_read (instream, template_sv) InStream *instream; SV *template_svPREINIT: 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) Kino_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 = 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 */ Kino_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; }}voidDESTROY(instream) InStream *instream;PPCODE: Kino_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 "KinoSearchUtilCarp.h"#include "KinoSearchUtilMathUtils.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 1024typedef struct instream { PerlIO *fh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -