format a binary string as hex dump

6 views
Skip to first unread message

Rainer Weikusat

unread,
May 6, 2021, 1:55:45 PMMay 6
to
Problem: Given a binary string of a principally indeterminate (max 8
length bytes), turn that into a hex dump with 16 bytes per line (and
possibly less on the last line.

Solution:

---------
sub format_bin
{
use bytes;
my @lines;
local *_ = \$_[0];

push(@lines, join(' ', unpack('(H2)*', $1)))
while /\G(.{1,16})/gs;

return @lines;
}
----------

I'm especially happy that there's no need to special-case the last line
as the /\G(.{1,16})/gs will match whatever is remains after the last
complete 16-character-group.

Henry Law

unread,
May 12, 2021, 9:59:30 AMMay 12
to
On Thu, 06 May 2021 18:55:38 +0100, Rainer Weikusat wrote:

> local *_ = \$_[0];

What witchcraft is that? I don't even know where to start looking it up.

--
Henry Law n e w s @ l a w s h o u s e . o r g
Manchester, England

Rainer Weikusat

unread,
May 12, 2021, 10:11:01 AMMay 12
to
Henry Law <ne...@lawshouse.org> writes:
> On Thu, 06 May 2021 18:55:38 +0100, Rainer Weikusat wrote:
>
>> local *_ = \$_[0];
>
> What witchcraft is that? I don't even know where to start looking it up.

It's documented in the "Symbol Tables" section of perlmod: *_ is the
typeglob whose scalar slot is $_. $_[0] is the scalar passed as first
argument (ie, at the implementation level, it's a SV *). Assigning a
reference to that to a glob causes the scalar slot of this glob to refer
to the scalar the reference came from: Afterwards (while the local is in
scope) $_ 'means' 'the scalar passed as first argument': It now has a
name but its contents weren't copied.

Kang-min Liu

unread,
May 12, 2021, 10:08:37 PMMay 12
to

Rainer Weikusat <rwei...@talktalk.net> writes:

# [1]
local *_ = \$_[0];

> ... to the scalar the reference came from: Afterwards (while the local is in
> scope) $_ 'means' 'the scalar passed as first argument': It now has a
> name but its contents weren't copied.

I wonder how it compares to this alternative:

# [2]
local $_ = $_[0];

I guess [1] is aliasing and [2] is copying, although I'm not 100%
confident about this (nor the exact meaning of aliasing.)

Rainer Weikusat

unread,
May 13, 2021, 5:44:41 PMMay 13
to
----
use Devel::Peek;

$a = 'Hi';

sub aa
{
local $_ = $_[0];
Dump($_);
}

sub bb
{
local *_ = \$_[0];
Dump($_);
}

Dump($a);
aa($a);
bb($a);
-----

For a sufficiently recent perl (tested on 5.24) the output will be


SV = PV(0x556a0e4dfb20) at 0x556a0e4fc7c8
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x556a0e507250 "Hi"\0
CUR = 2
LEN = 10
COW_REFCNT = 1
SV = PV(0x556a0e4dfc00) at 0x556a0e4def48
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x556a0e507250 "Hi"\0
CUR = 2
LEN = 10
COW_REFCNT = 2
SV = PV(0x556a0e4dfb20) at 0x556a0e4fc7c8
REFCNT = 2
FLAGS = (POK,IsCOW,pPOK)
PV = 0x556a0e507250 "Hi"\0
CUR = 2
LEN = 10
COW_REFCNT = 1

The aa subroutine creates a new scalar sharing the body of the other via
copy-on-write, the bb routine uses the passed scalar directly.

On older perls, aliasing in this way used to become faster than copying
the string for long strings (>> 100 characters). This is apparently
no longer the case when COW is supported.

Henry Law

unread,
May 14, 2021, 5:07:07 PMMay 14
to
On Wed, 12 May 2021 15:10:57 +0100, Rainer Weikusat wrote:

> It's documented in the "Symbol Tables" section of perlmod: *_ is the
> typeglob whose scalar slot is $_

Thank you. I confess that it's one of the areas of Perl with which I am
not familiar, so I should go and look at it.
Reply all
Reply to author
Forward
0 new messages