Set-SegmentTree

 view release on metacpan or  search on metacpan

lib/Set/SegmentTree/node.pm  view on Meta::CPAN

		);
		my $data = "\0\0\0\0";

		my @reloc = ({ offset => 0, item => $vtable, type => "signed negative delta" });
		# flatbuffers vtable offset is stored in negative form
		my @objects = ($vtable);

		if (defined $self->{min}) {
			$data .= pack 'l<', $self->{min};
		}

		if (defined $self->{low}) {
			$data .= pack 'l<', $self->{low};
		}

		if (defined $self->{max}) {
			$data .= pack 'l<', $self->{max};
		}

		if (defined $self->{high}) {
			$data .= pack 'l<', $self->{high};
		}

		if (defined $self->{split}) {
			$data .= pack 'l<', $self->{split};
		}

		if (defined $self->{segments}) {
			my ($array_object, @array_objects) = $self->serialize_array('[string]', $self->{segments}, $cache);
			push @objects, $array_object, @array_objects;
			push @reloc, { offset => length ($data), item => $array_object, type => 'unsigned delta'};
			$data .= "\0\0\0\0";
		}

		# pad to 4 byte boundary
		$data .= pack "x" x (4 - (length ($data) % 4)) if length ($data) % 4;

		# return table data and other objects that we've created
		return { type => "table", data => $data, reloc => \@reloc }, @objects
	}
}
	

sub serialize_objects {
	my ($self, @objects) = @_;


	my $data = "";
	my $offset = 0;

	# concatentate the data
	for my $object (@objects) {
		$object->{serialized_offset} = $offset;
		$data .= $object->{data};
		$offset += length $object->{data};
	}

	# second pass for writing offsets to other parts
	for my $object (@objects) {
		if (defined $object->{reloc}) {
			# perform address relocation
			for my $reloc (@{$object->{reloc}}) {
				my $value;
				if (defined $reloc->{lambda}) { # allow the reloc to have a custom format
					$value = $reloc->{lambda}($object, $reloc);
				} elsif (defined $reloc->{type} and $reloc->{type} eq "unsigned delta") {
					$value = pack "L<", $reloc->{item}{serialized_offset} - $object->{serialized_offset} - $reloc->{offset};
				} elsif (defined $reloc->{type} and $reloc->{type} eq "signed negative delta") {
					$value = pack "l<", $object->{serialized_offset} + $reloc->{offset} - $reloc->{item}{serialized_offset};
				} else {
					...
				}
				substr $data, $object->{serialized_offset} + $reloc->{offset}, length($value), $value;
			}
		}
	}

	# done, the data is now ready to be deserialized
	return $data
}

sub serialize_vtable {
	my ($self, @lengths) = @_;

	my $offset = 4;
	my @table;

	for (@lengths) { # parse table offsets
		push @table, $_ ? $offset : 0;
		$offset += $_;
	}

	unshift @table, $offset; # prefix data length
	unshift @table, 2 * (@table + 1); #prefix vtable length
	push @table, 0 if @table % 2; # pad if odd count
	# compile object
	return { type => "vtable", data => pack "S<" x @table, @table }
}

sub serialize_string {
	my ($self, $string) = @_;

	my $len = pack "L<", length $string;
	$string .= "\0"; # null termination byte because why the fuck not (it's part of flatbuffers)

	my $data = "$len$string";
	$data .= pack "x" x (4 - (length ($data) % 4)) if length ($data) % 4; # pad to 4 byte boundary

	return { type => "string", data => $data }
}


sub serialize_array {
	my ($self, $array_type, $array, $cache) = @_;

	$array_type = $array_type =~ s/\A\[(.*)\]\Z/$1/sr;

	my $data = pack "L<", scalar @$array;
	my @array_objects;
	my @reloc;



( run in 1.090 second using v1.01-cache-2.11-cpan-5511b514fd6 )