has
'uri'
=> (
is
=>
'ro'
,
isa
=>
'Str'
,
required
=> 1);
has
'flag'
=> (
is
=>
'ro'
,
isa
=> enum([
qw/r w/
]),
required
=> 1);
has
'handle'
=> (
is
=>
'rw'
,
isa
=>
'RecordIOHandle'
);
has
[
qw/writable
is_open/
] => (
is
=>
'rw'
,
isa
=>
'Bool'
);
sub
BUILD
{
my
$self
=
shift
;
$self
->is_open(0);
$self
->
open
();
}
sub
DEMOLISH
{
shift
->
close
;
}
method
open
()
{
my
$handle
;
if
(
$self
->flag eq
'w'
)
{
$handle
= check_call(AI::MXNetCAPI::RecordIOWriterCreate(
$self
->uri));
$self
->writable(1);
}
else
{
$handle
= check_call(AI::MXNetCAPI::RecordIOReaderCreate(
$self
->uri));
$self
->writable(0);
}
$self
->handle(
$handle
);
$self
->is_open(1);
}
method
close
()
{
return
if
not
$self
->is_open;
if
(
$self
->writable)
{
check_call(AI::MXNetCAPI::RecordIOWriterFree(
$self
->handle));
}
else
{
check_call(AI::MXNetCAPI::RecordIOReaderFree(
$self
->handle));
}
$self
->is_open(0);
}
method
reset
()
{
$self
->
close
;
$self
->
open
;
}
method
write
(Str
$buf
)
{
assert(
$self
->writable);
check_call(
AI::MXNetCAPI::RecordIOWriterWriteRecord(
$self
->handle,
$buf
,
length
(
$buf
)
)
);
}
method
read
()
{
assert(not
$self
->writable);
return
scalar
(check_call(
AI::MXNetCAPI::RecordIOReaderReadRecord(
$self
->handle,
)
));
}
method MXRecordIO(
@args
) {
return
AI::MXNet::RecordIO->new(
uri
=>
$args
[0],
flag
=>
$args
[1]) }
method MXIndexedRecordIO(
@args
)
{
return
AI::MXNet::IndexedRecordIO->new(
idx_path
=>
$args
[0],
uri
=>
$args
[1],
flag
=>
$args
[2]
)
}
has
[
qw/flag id id2/
] => (
is
=>
'rw'
,
isa
=>
'Int'
);
has
'label'
=> (
is
=>
'rw'
,
isa
=>
'AcceptableInput'
);
around
BUILDARGS
=>
sub
{
my
$orig
=
shift
;
my
$class
=
shift
;
if
(
@_
== 4)
{
return
$class
->
$orig
(
flag
=>
$_
[0],
label
=>
$_
[1],
id
=>
$_
[2],
id2
=>
$_
[3]);
}
return
$class
->
$orig
(
@_
);
};
my
@order
=
qw/flag label id id2/
;
use
overload
'@{}'
=>
sub
{
my
$self
=
shift
; [
map
{
$self
->
$_
}
@order
] };
method
unpack
(Str
$s
)
{
my
$h
;
my
$h_size
= 24;
(
$h
,
$s
) = (
substr
(
$s
, 0,
$h_size
),
substr
(
$s
,
$h_size
));
my
$header
= AI::MXNet::IRHeader->new(
unpack
(
'IfQQ'
,
$h
));
if
(
$header
->flag > 0)
{
my
$label
;
(
$label
,
$s
) = (
substr
(
$s
, 0, 4
*$header
->flag),
substr
(
$s
, 4
*$header
->flag));
my
$pdl_type
= PDL::Type->new(DTYPE_MX_TO_PDL->{float32});
my
$pdl
= PDL->new_from_specification(
$pdl_type
,
$header
->flag);
${
$pdl
->get_dataref} =
$label
;
$pdl
->upd_data;
$header
->label(
$pdl
);
}
return
(
$header
,
$s
)
}
method
pack
(AI::MXNet::IRHeader|ArrayRef
$header
, Str
$s
)
{
$header
= AI::MXNet::IRHeader->new(
@$header
)
unless
blessed
$header
;
if
(not
ref
$header
->label)
{
$header
->flag(0);
}
else
{
my
$label
= AI::MXNet::NDArray->array(
$header
->label,
dtype
=>
'float32'
)->aspdl;
$header
->label(0);
$header
->flag(
$label
->nelem);
my
$buf
= ${
$label
->get_dataref};
$s
=
"$buf$s"
;
}
$s
=
pack
(
'IfQQ'
, @{
$header
}) .
$s
;
return
$s
;
}
has
'idx_path'
=> (
is
=>
'ro'
,
isa
=>
'Str'
,
required
=> 1);
has
[
qw/idx
keys fidx/
] => (
is
=>
'rw'
,
init_arg
=>
undef
);
method
open
()
{
$self
->SUPER::
open
();
$self
->idx({});
$self
->
keys
([]);
open
(
my
$f
,
$self
->flag eq
'r'
?
'<'
:
'>'
,
$self
->idx_path);
$self
->fidx(
$f
);
if
(not
$self
->writable)
{
while
(<
$f
>)
{
chomp
;
my
(
$key
,
$val
) =
split
(/\t/);
push
@{
$self
->
keys
},
$key
;
$self
->idx->{
$key
} =
$val
;
}
}
}
method
close
()
{
return
if
not
$self
->is_open;
$self
->SUPER::
close
();
$self
->fidx(
undef
);
}
method
seek
(Int
$idx
)
{
assert(not
$self
->writable);
my
$pos
=
$self
->idx->{
$idx
};
check_call(AI::MXNetCAPI::RecordIOReaderSeek(
$self
->handle,
$pos
));
}
method
tell
()
{
assert(
$self
->writable);
return
scalar
(check_call(AI::MXNetCAPI::RecordIOWriterTell(
$self
->handle)));
}
method read_idx(Int
$idx
)
{
$self
->
seek
(
$idx
);
return
$self
->
read
();
}
method write_idx(Int
$idx
, Str
$buf
)
{
my
$pos
=
$self
->
tell
();
$self
->
write
(
$buf
);
my
$f
=
$self
->fidx;
print
$f
"$idx\t$pos\n"
;
$self
->idx->{
$idx
} =
$pos
;
push
@{
$self
->
keys
},
$idx
;
}
1;