package xm::hash;
use xm::o;

# the external hash format is using a normal dd/dt description.
# both keys and values are assumed to be in xml'ish form.
# to secure the local metamarkups, the tags carry a "class=p"
# attribute in both the start and end-markers

# encode a one-level hash to its xml'ish format
sub encode1
{
    my $h = shift;
    my $k;
    my $T = "";

    for $k (sort keys %$h)
    {
	$T .= "<dt class=p>".$k."</dt class=p>"
	    ."\n<dd class=p>".$$h{$k}."</dd class=p>\n";
    }
    return $T;
}

# decode a one-level hash from its xml'ish format
# the space-secured format is assumed.
sub decode1
{
    my $T = shift;
    my $h = { };
    my $k;

    $T =~ s{<dt\ class=p(?=>)((?:.(?!</?dt\ class=p>))*.)
		</dt\ class=p>
		\s*<dd\ class=p(?=>)((?:.(?!</?dd\ class=p>))*.)
		    </dd\ class=p>}{
	$$h{$1} = $2;
	""
	}gsex;
    return $h;
}

# encode a two-level hash to its xml'ish format
sub encode2     
{
    my $h = shift;
    my $k;
    my $T = "";
    for $k (sort keys %$k)
    {
	$T .= "<h6 class=p>".$k."</h6 class=p>\n<dl class=p>\n";
	$T .= encode1($h{$k});
	$T .= "</dl class=p>\n";
    }
    return $T;
}

# decode a two-level hash from its xml'ish format
sub decode2
{
    my $T = shift;
    my $h = { };
    my $k;

    $T =~ s{<h6\ class=p(?=>)((?:.(?!</?h6\ class=p>))*.)
		</h6\ class=p>
		\s*<dl\ class=p(?=>)((?:.(?!</?dl\ class=p>))*.)
		    </dl\ class=p>}{
	$$h{$1} = decode1($2);
	""
	}gsex;
    return $h;
}

sub DESC {"
  flatten a file - my use an encode2' file, but read it with 
  decode1 and then spit it out again with encode2
"};

sub DO
{
    my $in = shift;
    return encode1(decode1($in));
}

sub ARGS { return    xm::o::args_stdin(@_,DESC); }
sub main { return DO(xm::o::args_stdin(@_,DESC)); }