Algorithm-FEC
view release on metacpan or search on metacpan
{
free_files (self);
Newz (0, self->b_addr, self->dp, void *);
Newz (0, self->b_mmap, self->dp, void *);
Newz (0, self->b_sz , self->dp, int);
Newz (0, self->b_sv , self->dp, SV *);
}
static void
force_addrs (struct state *self, int dp)
{
int i;
for (i = 0; i < dp; i++)
if (self->b_sv[i])
{
STRLEN size;
self->b_addr[i] = SvPV_force (self->b_sv[i], size);
if (size != self->sz)
croak ("block #%d (a string) has size %d, not %d", i, (int)size, self->sz);
} else if (!self->b_mmap[i]) {
croak ("block #%d neither string nor file, did set_blocks fail and you ignored it?", i);
}
}
static void
open_file (struct state *self, int idx, SV *sv, int rw)
{
IO *io = 0;
off_t offset;
if (SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV)
{
io = sv_2io (*av_fetch ((AV *)SvRV (sv), 0, 1));
offset = SvIV (*av_fetch ((AV *)SvRV (sv), 1, 1));
sv = 0;
}
else if (!SvPOK (sv))
{
io = sv_2io (sv);
offset = 0;
sv = 0;
}
if (io)
{
int fd = PerlIO_fileno (IoIFP (io));
off_t ofs2 = offset & ~((off_t)getpagesize () - 1);
void *mm;
if (fd <= 0)
croak ("invalid file descriptor for block #%d", idx);
mm = mmap (0, self->sz + (offset - ofs2),
rw ? PROT_READ | PROT_WRITE : PROT_READ,
MAP_SHARED, fd, ofs2);
if (mm == MAP_FAILED)
croak ("unable to mmap block #%d (wrong offset or size?): %s", idx, strerror (errno));
self->b_mmap[idx] = mm;
self->b_addr[idx] = (void *)((char *)mm + (offset - ofs2));
self->b_sz [idx] = self->sz + (offset - ofs2);
}
else if (sv)
self->b_sv[idx] = SvREFCNT_inc (sv);
else
croak ("unable to open block #%d, must be either string, filehandle, or [filehandle, offset]", idx);
}
static void
open_files (struct state *self, AV *av, int rw)
{
int i;
realloc_files (self);
for (i = 0; i < self->dp; i++)
open_file (self, i, *av_fetch (av, i, 1), rw);
}
MODULE = Algorithm::FEC PACKAGE = Algorithm::FEC
PROTOTYPES: ENABLE
Algorithm::FEC
new(class, data_packets, encoded_packets, blocksize)
SV * class
int data_packets
int encoded_packets
int blocksize
CODE:
void *code;
struct fec_imp *imp;
if (data_packets < 2)
croak ("the number of data packets must be >= 2"); /* for copy_blocks :) */
if (encoded_packets < data_packets)
croak ("the number of encoded packets must be >= the number of data packets");
if (GF_SIZE16 < encoded_packets)
croak ("the number of encoded packets must be <= %d", GF_SIZE16);
imp = GF_SIZE8 < encoded_packets ? &fec16_imp : &fec8_imp;
code = imp->fec_new (data_packets, encoded_packets);
if (!code)
croak ("FATAL: unable to create fec state");
Newz(0, RETVAL, 1, struct state);
RETVAL->imp = imp;
RETVAL->code = code;
RETVAL->sz = blocksize;
RETVAL->dp = data_packets;
RETVAL->ep = encoded_packets;
OUTPUT:
RETVAL
RETVAL = newSV (self->sz);
if (!RETVAL)
croak ("unable to allocate result block (out of memory)");
SvPOK_only (RETVAL);
SvCUR_set (RETVAL, self->sz);
self->imp->fec_encode (self->code, self->b_addr,
SvPVX (RETVAL), block_index, self->sz);
OUTPUT:
RETVAL
void
set_decode_blocks (self, blocks, indices)
Algorithm::FEC self
SV * blocks
SV * indices
ALIAS:
shuffle = 1
CODE:
{
int i;
int *idx;
chk_array (blocks, self->dp, "set_decode_blocks", "blocks");
chk_array (indices, self->dp, "set_decode_blocks", "indices");
Newz (0, idx, self->dp, int);
/* copy and check */
for (i = 0; i < self->dp; i++)
{
idx[i] = SvIV (*av_fetch ((AV *)SvRV (indices), i, 1));
if (idx[i] < 0 || idx[i] >= self->ep)
{
Safefree (idx);
croak ("index %d in array out of bounds (0 <= %d < %d != true)",
i, idx[i], self->ep);
}
}
/*
* do the same shuffling as fec_decode does here,
* so we know the order.
*/
for (i = 0; i < self->dp; i++)
while (idx[i] < self->dp && idx[i] != i)
{
SV **a, **b, **e, **f;
int d;
void *p;
SV *s;
int j = idx[i];
if (idx[j] == j)
{
Safefree (idx);
croak ("error while shuffling, duplicate indices?");
}
a = av_fetch ((AV *)SvRV (indices), i, 1);
b = av_fetch ((AV *)SvRV (indices), j, 1);
e = av_fetch ((AV *)SvRV (blocks ), i, 1);
f = av_fetch ((AV *)SvRV (blocks ), j, 1);
d = idx[i]; idx[i] = idx[j]; idx[j] = d;
s = *a; *a = *b; *b = s;
s = *e; *e = *f; *f = s;
}
if (ix)
Safefree (idx);
else
{
open_files (self, (AV *)SvRV (blocks), 1);
self->idx = idx;
}
}
void
decode (self)
Algorithm::FEC self
CODE:
if (!self->idx)
croak ("index array must be set by a prior call to set_decode_blocks");
force_addrs (self, self->dp);
self->imp->fec_decode (self->code, self->b_addr, self->idx, self->sz);
free_files (self);
void
copy (self, srcblock, dstblock)
Algorithm::FEC self
SV * srcblock
SV * dstblock
CODE:
realloc_files (self);
open_file (self, 0, srcblock, 0);
open_file (self, 1, dstblock, 1);
force_addrs (self, 2);
Copy (self->b_addr[0], self->b_addr[1], self->sz, char);
free_files (self);
void
DESTROY(self)
Algorithm::FEC self
CODE:
self->imp->fec_free (self->code);
free_files (self);
Safefree(self);
( run in 0.579 second using v1.01-cache-2.11-cpan-f6376fbd888 )