Thread Array zippen/Entpacken (10 answers)
Opened by ITobiI at 2015-10-14 11:34

Gast janus
 2015-10-14 15:46
#182605 #182605
Und ich bin für Selber bauen, weil ich dann den Algorithmus kenne und den auch in JavaScript implementieren kann :)

Ne, im Ernst, das sind nur 100 Zeilen:


Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package bSerialize;

# Verschiedene Algorithmen zum Serialisieren von Datenstrukturen
# in Bytesequenzen und umgekehrt

use strict;
use warnings;
use bytes;
use IO::String;

sub new{ return bless{
    valcache => {}
}, shift }

# Vereinbarung in einem Byte (pack 'C'), was den Wert betrifft
# 0 => undef  null
# 1 => ''     Leerstring
# Datentypen könnten folgen
# Ansonsten ist bei 1 alles String

# Kleinste atomare Einheit
sub val2bin{
    my $self = shift;
    my $val = shift;

    return pack('NC',0,0) if ! defined $val;
    
    my %cache = %{$self->{valcache}};
    return $cache{$val} ? $cache{$val} : do{
        my $bs = pack('NC', length($val), 1).$val; 
        $cache{$val} = $bs;
        $bs;
    };
}

# Array to Binary Sequence
sub array2bin{
    my $self = shift;
    my $aref = shift;
    my $bs   = '';
    foreach my $e(@$aref){ $bs .= $self->val2bin($e)  }
    return $bs;
}

# Binary Sequence to Array
sub bin2array{
    my $self = shift;
    my $bs   = shift; # Referenz!!!

    my $io = IO::String->new;
    $io->print($$bs);
    $io->seek(0,0);
    my @ret = ();
    while( read($io, my $buffer, 5)  ){
        my ($len, $type) = unpack('NC', $buffer);
        read($io, my $elem, $len);
        if( $type == 0){ push @ret, undef }
        else           { push @ret, $elem }
    }
    return \@ret;
}

# Attribute Value, Hash to binary sequence
sub av2bin{
    my $self = shift;
    my $av = shift;
    my $bs = '';
    foreach my $att( keys %$av ){ $bs .= $self->val2bin($att).$self->val2bin($av->{$att})  }
    return $bs;
}

# binary sequence to hash (attribute, value)
sub bin2av{
    my $self = shift;
    my $bs = shift;
    my %ret = @{$self->bin2array($bs)};
    return \%ret;
}

# Entity Attribute Value
# Ent != '' und Att != ''
sub eav2bin{
    my $self = shift;
    my $eav = shift;
    my $bs = '';
    foreach my $ent(keys %$eav){
        foreach my $att(keys %{$eav->{$ent}}){
            $bs .= $self->val2bin($ent).$self->val2bin($att).$self->val2bin( $eav->{$ent}{$att} );
        }
    }
    return $bs;
}

# Entity Attribute Value
sub bin2eav(){
    my $self = shift;
    my $bs = shift; # Referenz!!!
    my $raw = $self->bin2array($bs);
    my $eav = {};
    while( my $ent = shift @$raw){
        my $att = shift @$raw;
        my $val = shift @$raw;
        $eav->{$ent}{$att} = $val;
    }
    return $eav;
}

1;#########################################################################
#__END__
use Data::Dumper;

my $bs = bSerialize->new();

# All in One: Hash, Array, Hash of Hashes (EAV)
my $bin = $bs->av2bin({
    addr => $bs->av2bin( { name => 'foo', vname => 'bar', city => 'NY', nix => '', garnix => undef } ),
    nums => $bs->array2bin( [undef, 0, 1, 2, 3, 9] ),
    eav  => $bs->eav2bin({ env => \%ENV, sig => \%SIG })
});

print Dumper $bin,
    $bs->bin2av( \$bs->bin2av(\$bin)->{addr} ),
    $bs->bin2array( \$bs->bin2av(\$bin)->{nums} ),
    $bs->bin2eav( \$bs->bin2av(\$bin)->{eav} );

Last edited: 2015-10-14 15:54:39 +0200 (CEST)

View full thread Array zippen/Entpacken