| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| |
| use Scalar::Util qw(reftype looks_like_number); |
| |
| =pod |
| |
| =head1 NAME |
| |
| qpid::proton::Data |
| |
| =head1 DESCRIPTION |
| |
| The B<Data> class provides an interface for decoding, extract, creating and |
| encoding arbitrary AMQP data. A B<Data> object contains a tree of AMQP values. |
| Leaf nodes in this tree correspond to scalars in the AMQP type system such as |
| B<INT> or B<STRING>. Integerior nodes in this tree correspond to compound values |
| in the AMQP type system such as B<LIST>, B<MAP>, B<ARRAY> or B<DESCRIBED>. The |
| root node of the tree is the B<Data> object itself and can have an arbitrary |
| number of children. |
| |
| A B<Data> object maintains the notion of the current sibling node and a current |
| parent node. Siblings are ordered within their parent. Values are accessed |
| and/or added by using the B<next>, B<prev>, B<enter> and B<exit> methods to |
| navigate to the desired location in the tree and using the supplied variety of |
| mutator and accessor methods to access or add a value of the desired type. |
| |
| The mutator methods will always add a vlaue I<after> the current node in the |
| tree. If the current node has a next sibling the mutaor method will overwrite |
| the value on this node. If there is no current node or the current node has no |
| next sibling then one will be added. The accessor methods always set the |
| add/modified node to the current node. The accessor methods read the value of |
| the current node and do not change which node is current. |
| |
| =cut |
| |
| package qpid::proton::Data; |
| |
| =pod |
| |
| =head1 CONSTRUCTOR |
| |
| Creates a new instance with the specified capacity. |
| |
| =over |
| |
| =item my $data = qpid::proton::Data->new( CAPACITY ); |
| |
| =back |
| |
| =cut |
| |
| sub new { |
| my ($class) = @_; |
| my ($self) = {}; |
| my $capacity = $_[1] || 16; |
| my $impl = $capacity; |
| $self->{_free} = 0; |
| |
| if($capacity) { |
| if (::looks_like_number($capacity)) { |
| $impl = cproton_perl::pn_data($capacity); |
| $self->{_free} = 1; |
| } |
| } |
| |
| $self->{_impl} = $impl; |
| |
| bless $self, $class; |
| return $self; |
| } |
| |
| sub DESTROY { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_free($impl) if $self->{_free}; |
| } |
| |
| =pod |
| |
| =head1 ACTIONS |
| |
| Clear all content for the data object. |
| |
| =over |
| |
| =item my $data->clear(); |
| |
| =back |
| |
| =cut |
| |
| sub clear { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_clear($impl); |
| } |
| |
| |
| =pod |
| |
| =head1 NAVIGATION |
| |
| The following methods allow for navigating through the nodes in the tree. |
| |
| =cut |
| |
| |
| =pod |
| |
| =over |
| |
| =item $doc->enter; |
| |
| =item if ($doc->enter()) { do_something_with_children; } |
| |
| Sets the parent node to the current node and clears the current node. |
| |
| Clearing the current node sets it I<before> the first child. |
| |
| =item $doc->exit; |
| |
| =item if ($doc->exit()) { do_something_with_parent; } |
| |
| Sets the current node to the parent node, and the parent node to its own parent. |
| |
| =item $doc->next; |
| |
| =item $doc->prev; |
| |
| Moves to the next/previous sibling and returns its type. If there is no next or |
| previous sibling then the current node remains unchanged. |
| |
| =item $doc->rewind; |
| |
| Clears the current node and sets the parent to the root node. |
| |
| =back |
| |
| =cut |
| |
| sub enter { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_enter($impl); |
| } |
| |
| sub exit { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_exit($impl); |
| } |
| |
| sub rewind { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_rewind($impl); |
| } |
| |
| |
| =pod |
| |
| =over |
| |
| =item $doc->next; |
| |
| =item if ($doc->next()) { do_something; } |
| |
| Advances the current node to its next sibling and returns its type. |
| |
| If there is no next sibling then the current node remains unchanged and |
| B<undef> is returned. |
| |
| =item $doc->prev; |
| |
| =item if ($doc->prev()) { do_something; } |
| |
| Advances the current node to its previous sibling and returns its type. |
| |
| If there is no previous sibling then the current node remains unchanged and |
| undef is returned. |
| |
| =back |
| |
| =cut |
| |
| sub next { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| return cproton_perl::pn_data_next($impl); |
| } |
| |
| sub prev { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| return cproton_perl::pn_data_prev($impl); |
| } |
| |
| |
| =pod |
| |
| =head1 SUPPORTED TYPES |
| |
| The following methods allow for inserting the various node types into the |
| tree. |
| |
| =head2 NODE TYPE |
| |
| You can retrieve the type of the current node. |
| |
| =over |
| |
| =item $type = $doc->get_type; |
| |
| =back |
| |
| =cut |
| |
| |
| sub get_type { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $type = cproton_perl::pn_data_type($impl); |
| |
| return qpid::proton::Mapping->find_by_type_value($type); |
| } |
| |
| |
| =pod |
| |
| =head2 SCALAR TYPES |
| |
| =cut |
| |
| =pod |
| |
| =head3 NULL |
| |
| =over |
| |
| =item $doc->put_null; |
| |
| Inserts a null node. |
| |
| =item $doc->is_null; |
| |
| Returns true if the current node is null. |
| |
| =back |
| |
| =cut |
| |
| sub put_null() { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_put_null($impl); |
| } |
| |
| sub is_null { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_is_null($impl); |
| } |
| |
| sub check { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $err = $_[1]; |
| |
| # if we got a null then just exit |
| return $err if !defined($err); |
| |
| if($err < 0) { |
| die DataException->new("[$err]: " . cproton_perl::pn_data_error($impl)); |
| } else { |
| return $err; |
| } |
| } |
| |
| =pod |
| |
| =head3 BOOL |
| |
| Handles a boolean (B<true>/B<false>) node. |
| |
| =over |
| |
| =item $doc->put_bool( VALUE ); |
| |
| =item $doc->get_bool; |
| |
| =back |
| |
| =cut |
| |
| sub put_bool { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1] || 0; |
| |
| cproton_perl::pn_data_put_bool($impl, $value); |
| } |
| |
| sub get_bool { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_bool($impl); |
| } |
| |
| =pod |
| |
| =head3 UBYTE |
| |
| Handles an unsigned byte node. |
| |
| =over |
| |
| =item $data->put_ubyte( VALUE ); |
| |
| =item $data->get_ubyte; |
| |
| =back |
| |
| =cut |
| |
| sub put_ubyte { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "ubyte must be defined" if !defined($value); |
| die "ubyte must be non-negative" if $value < 0; |
| |
| check(cproton_perl::pn_data_put_ubyte($impl, int($value))); |
| } |
| |
| sub get_ubyte { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_ubyte($impl); |
| } |
| |
| =pod |
| |
| =head3 BYTE |
| |
| Handles a signed byte node. |
| |
| =over |
| |
| =item $data->put_byte( VALUE ); |
| |
| =item $data->get_byte; |
| |
| =back |
| |
| =cut |
| |
| sub put_byte { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "byte must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_byte($impl, int($value))); |
| } |
| |
| sub get_byte { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_byte($impl); |
| } |
| |
| =pod |
| |
| =head3 USHORT |
| |
| Handles an unsigned short node. |
| |
| =over |
| |
| =item $data->put_ushort( VALUE ); |
| |
| =item $data->get_ushort; |
| |
| =back |
| |
| =cut |
| |
| sub put_ushort { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "ushort must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_ushort($impl, int($value))); |
| } |
| |
| sub get_ushort { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_ushort($impl); |
| } |
| |
| =pod |
| |
| =head3 SHORT |
| |
| Handles a signed short node. |
| |
| =over |
| |
| =item $data->put_short( VALUE ); |
| |
| =item $data->get_short; |
| |
| =back |
| |
| =cut |
| |
| sub put_short { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "short must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_short($impl, int($value))); |
| } |
| |
| sub get_short { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_short($impl); |
| } |
| |
| =pod |
| |
| =head3 UINT |
| |
| Handles an unsigned integer node. |
| |
| =over |
| |
| =item $data->put_uint( VALUE ); |
| |
| =item $data->get_uint; |
| |
| =back |
| |
| =cut |
| |
| sub put_uint { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "uint must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_uint($impl, int($value))); |
| } |
| |
| sub get_uint { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_uint($impl); |
| } |
| |
| =pod |
| |
| =head3 INT |
| |
| Handles an integer node. |
| |
| =over |
| |
| =item $data->put_int( VALUE ); |
| |
| =item $data->get_int; |
| |
| =back |
| |
| =cut |
| |
| sub put_int { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "int must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_int($impl, int($value))); |
| } |
| |
| sub get_int { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_int($impl); |
| } |
| |
| =pod |
| |
| =head3 CHAR |
| |
| Handles a character node. |
| |
| =over |
| |
| =item $data->put_char( VALUE ); |
| |
| =item $data->get_char; |
| |
| =back |
| |
| =cut |
| |
| sub put_char { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "char must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_char($impl, int($value))); |
| } |
| |
| sub get_char { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_char($impl); |
| } |
| |
| =pod |
| |
| =head3 ULONG |
| |
| Handles an unsigned long node. |
| |
| =over |
| |
| =item $data->set_ulong( VALUE ); |
| |
| =item $data->get_ulong; |
| |
| =back |
| |
| =cut |
| |
| sub put_ulong { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "ulong must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_ulong($impl, $value)); |
| } |
| |
| sub get_ulong { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_ulong($impl); |
| } |
| |
| =pod |
| |
| =head3 LONG |
| |
| Handles a signed long node. |
| |
| =over |
| |
| =item $data->put_long( VALUE ); |
| |
| =item $data->get_long; |
| |
| =back |
| |
| =cut |
| |
| sub put_long { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "long must be defined" if !defined($value); |
| |
| cproton_perl::pn_data_put_long($impl, int($value)); |
| } |
| |
| sub get_long { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_long($impl); |
| } |
| |
| =pod |
| |
| =head3 TIMESTAMP |
| |
| Handles a timestamp node. |
| |
| =over |
| |
| =item $data->put_timestamp( VALUE ); |
| |
| =item $data->get_timestamp; |
| |
| =back |
| |
| =cut |
| |
| sub put_timestamp { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "timestamp must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_timestamp($impl, int($value))); |
| } |
| |
| sub get_timestamp { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_timestamp($impl); |
| } |
| |
| =pod |
| |
| =head3 FLOAT |
| |
| Handles a floating point node. |
| |
| =over |
| |
| =item $data->put_float( VALUE ); |
| |
| =item $data->get_float; |
| |
| =back |
| |
| =cut |
| |
| sub put_float { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "float must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_float($impl, $value)); |
| } |
| |
| sub get_float { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| my $value = cproton_perl::pn_data_get_float($impl); |
| |
| cproton_perl::pn_data_get_float($impl); |
| } |
| |
| =pod |
| |
| =head3 DOUBLE |
| |
| Handles a double node. |
| |
| =over |
| |
| =item $data->put_double( VALUE ); |
| |
| =item $data->get_double; |
| |
| =back |
| |
| =cut |
| |
| sub put_double { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "double must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_double($impl, $value)); |
| } |
| |
| sub get_double { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_double($impl); |
| } |
| |
| =pod |
| |
| =head3 DECIMAL32 |
| |
| Handles a decimal32 node. |
| |
| =over |
| |
| =item $data->put_decimal32( VALUE ); |
| |
| =item $data->get_decimal32; |
| |
| =back |
| |
| =cut |
| |
| sub put_decimal32 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "decimal32 must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_decimal32($impl, $value)); |
| } |
| |
| sub get_decimal32 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_decimal32($impl); |
| } |
| |
| =pod |
| |
| =head3 DECIMAL64 |
| |
| Handles a decimal64 node. |
| |
| =over |
| |
| =item $data->put_decimal64( VALUE ); |
| |
| =item $data->get_decimal64; |
| |
| =back |
| |
| =cut |
| |
| sub put_decimal64 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "decimal64 must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_decimal64($impl, $value)); |
| } |
| |
| sub get_decimal64 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_decimal64($impl); |
| } |
| |
| =pod |
| |
| =head3 DECIMAL128 |
| |
| Handles a decimal128 node. |
| |
| =over |
| |
| =item $data->put_decimal128( VALUE ); |
| |
| =item $data->get_decimal128; |
| |
| =back |
| |
| =cut |
| |
| sub put_decimal128 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "decimal128 must be defined" if !defined($value); |
| |
| my @binary = split //, pack("H[32]", sprintf("%032x", $value)); |
| my @bytes = (); |
| |
| foreach $char (@binary) { |
| push(@bytes, ord($char)); |
| } |
| check(cproton_perl::pn_data_put_decimal128($impl, \@bytes)); |
| } |
| |
| sub get_decimal128 { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| my $bytes = cproton_perl::pn_data_get_decimal128($impl); |
| my $value = hex(unpack("H[32]", $bytes)); |
| |
| return $value; |
| } |
| |
| =pod |
| |
| =head3 UUID |
| |
| Handles setting a UUID value. UUID values can be set using a 128-bit integer |
| value or else a well-formed string. |
| |
| =over |
| |
| =item $data->put_uuid( VALUE ); |
| |
| =item $data->get_uuid; |
| |
| =back |
| |
| =cut |
| |
| use Data::Dumper; |
| |
| sub put_uuid { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "uuid must be defined" if !defined($value); |
| |
| if($value =~ /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/) { |
| $value =~ s/-//g; |
| my @binary = split //, pack("H[32]", $value); |
| my @bytes = (); |
| |
| foreach $char (@binary) { |
| push(@bytes, ord($char)); |
| } |
| |
| check(cproton_perl::pn_data_put_uuid($impl, \@bytes)); |
| } else { |
| die "uuid is malformed: $value"; |
| } |
| } |
| |
| sub get_uuid { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| my $bytes = cproton_perl::pn_data_get_uuid($impl); |
| |
| my $value = unpack("H[32]", $bytes); |
| $value = substr($value, 0, 8) . "-" . |
| substr($value, 8, 4) . "-" . |
| substr($value, 12, 4) . "-" . |
| substr($value, 16, 4) . "-" . |
| substr($value, 20); |
| |
| return $value; |
| } |
| |
| =pod |
| |
| =head3 BINARY |
| |
| Handles a binary data node. |
| |
| =over |
| |
| =item $data->put_binary( VALUE ); |
| |
| =item $data->get_binary; |
| |
| =back |
| |
| =cut |
| |
| sub put_binary { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "binary must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_binary($impl, $value)) if defined($value); |
| } |
| |
| sub get_binary { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_binary($impl); |
| } |
| |
| =pod |
| |
| =head3 STRING |
| |
| Handles a string node. |
| |
| =over |
| |
| =item $data->put_string( VALUE ); |
| |
| =item $data->get_string; |
| |
| =back |
| |
| =cut |
| |
| sub put_string { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "string must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_string($impl, $value)); |
| } |
| |
| sub get_string { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_string($impl); |
| } |
| |
| =pod |
| |
| =head3 SYMBOL |
| |
| Handles a symbol value. |
| |
| =over |
| |
| =item $data->put_symbol( VALUE ); |
| |
| =item $data->get_symbol; |
| |
| =back |
| |
| =cut |
| |
| sub put_symbol { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $value = $_[1]; |
| |
| die "symbol must be defined" if !defined($value); |
| |
| check(cproton_perl::pn_data_put_symbol($impl, $value)); |
| } |
| |
| sub get_symbol { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_symbol($impl); |
| } |
| |
| =pod |
| |
| =head3 DESCRIBED VALUE |
| |
| A described node has two children: the descriptor and the value. |
| |
| These are specified by entering the node and putting the |
| described values. |
| |
| =over |
| |
| =item $data->put_described; |
| |
| =item $data->is_described; |
| |
| =back |
| |
| =cut |
| |
| sub put_described { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_put_described($impl); |
| } |
| |
| sub is_described { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_is_described($impl); |
| } |
| |
| =pod |
| |
| =head3 ARRAYS |
| |
| Puts an array value. |
| |
| Elements may be filled by entering the array node and putting the element values. |
| The values must all be of the specified array element type. |
| |
| If an array is B<described> then the first child value of the array is the |
| descriptor and may be of any type. |
| |
| =over |
| |
| B<DESCRIBED> specifies whether the array is described or not. |
| |
| B<TYPE> specifies the type of elements in the array. |
| |
| =back |
| |
| =over |
| |
| =item $data->put_array( DESCRIBED, TYPE ) |
| |
| =item my ($count, $described, $array_type) = item $data->get_array |
| |
| =back |
| |
| =cut |
| |
| sub put_array { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| my $described = $_[1] || 0; |
| my $array_type = $_[2]; |
| |
| die "array type must be defined" if !defined($array_type); |
| |
| check(cproton_perl::pn_data_put_array($impl, |
| $described, |
| $array_type->get_type_value)); |
| } |
| |
| sub get_array { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| my $count = cproton_perl::pn_data_get_array($impl); |
| my $described = cproton_perl::pn_data_is_array_described($impl); |
| my $type_value = cproton_perl::pn_data_get_array_type($impl); |
| |
| $type_value = qpid::proton::Mapping->find_by_type_value($type_value); |
| |
| return ($count, $described, $type_value); |
| } |
| |
| sub get_array_type { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_array_type($impl); |
| } |
| |
| =pod |
| |
| =head3 LIST |
| |
| Puts a list value. |
| |
| Elements may be filled in by entering the list and putting element values. |
| |
| =over |
| |
| =item $data->put_list; |
| |
| =item my $count = $data->get_list |
| |
| =back |
| |
| =cut |
| |
| sub put_list { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| check(cproton_perl::pn_data_put_list($impl)); |
| } |
| |
| sub get_list { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_list($impl); |
| } |
| |
| =pod |
| |
| head3 MAP |
| |
| Puts a map value. |
| |
| Elements may be filled by entering the map node and putting alternating |
| key/value pairs. |
| |
| =over |
| |
| =item $data->put_map; |
| |
| =item my $count = $data->get_map; |
| |
| =back |
| |
| =cut |
| |
| sub put_map { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| check(cproton_perl::pn_data_put_map($impl)); |
| } |
| |
| sub get_map { |
| my ($self) = @_; |
| my $impl = $self->{_impl}; |
| |
| cproton_perl::pn_data_get_map($impl); |
| } |
| |
| sub put_list_helper { |
| my ($self) = @_; |
| my ($array) = $_[1]; |
| |
| $self->put_list; |
| $self->enter; |
| |
| for my $value (@{$array}) { |
| if (qpid::proton::utils::is_num($value)) { |
| if (qpid::proton::utils::is_float($value)) { |
| $self->put_float($value); |
| } else { |
| $self->put_int($value); |
| } |
| } elsif (!defined($value)) { |
| $self->put_null; |
| } elsif ($value eq '') { |
| $self->put_string($value); |
| } elsif (ref($value) eq 'HASH') { |
| $self->put_map_helper($value); |
| } elsif (ref($value) eq 'ARRAY') { |
| $self->put_list_helper($value); |
| } else { |
| $self->put_string($value); |
| } |
| } |
| |
| $self->exit; |
| } |
| |
| sub get_list_helper { |
| my ($self) = @_; |
| my $result = []; |
| my $type = $self->get_type; |
| |
| if ($cproton_perl::PN_LIST == $type->get_type_value) { |
| my $size = $self->get_list; |
| |
| $self->enter; |
| |
| for(my $count = 0; $count < $size; $count++) { |
| if ($self->next) { |
| my $value_type = $self->get_type; |
| my $value = $value_type->get($self); |
| |
| push(@{$result}, $value); |
| } |
| } |
| |
| $self->exit; |
| } |
| |
| return $result; |
| } |
| |
| sub put_map_helper { |
| my ($self) = @_; |
| my $hash = $_[1]; |
| |
| $self->put_map; |
| $self->enter; |
| |
| foreach(keys %{$hash}) { |
| my $key = $_; |
| my $value = $hash->{$key}; |
| |
| my $keytype = ::reftype($key); |
| my $valtype = ::reftype($value); |
| |
| if ($keytype eq ARRAY) { |
| $self->put_list_helper($key); |
| } elsif ($keytype eq "HASH") { |
| $self->put_map_helper($key); |
| } else { |
| $self->put_string("$key"); |
| } |
| |
| if (::reftype($value) eq HASH) { |
| $self->put_map_helper($value); |
| } elsif (::reftype($value) eq ARRAY) { |
| $self->put_list_helper($value); |
| } else { |
| $self->put_string("$value"); |
| } |
| } |
| |
| $self->exit; |
| } |
| |
| sub get_map_helper { |
| my ($self) = @_; |
| my $result = {}; |
| my $type = $self->get_type; |
| |
| if ($cproton_perl::PN_MAP == $type->get_type_value) { |
| my $size = $self->get_map; |
| |
| $self->enter; |
| |
| for($count = 0; $count < $size; $count++) { |
| if($self->next) { |
| my $key = $self->get_type->get($self); |
| if($self->next) { |
| my $value = $self->get_type->get($self); |
| $result->{$key} = $value; |
| } |
| } |
| } |
| |
| $self->exit; |
| |
| } |
| |
| return $result; |
| } |
| |
| 1; |