# format a binary string as hex dump

6 views

### Rainer Weikusat

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

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

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

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%

### Rainer Weikusat

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.