package CFX5::IO::Data;

use strict;
use vars qw(@ISA);

use CFX5::IO::Const qw(:IOP_DATARR);		# for the IOP_* definitions

# Preloaded methods go here.

sub new {
  my $class=shift;
  my $type=ref($class) || $class;
  my $hdr=CFX5::IO::Data::NEW();
  bless $hdr,$type;
  $hdr;
}

sub DESTROY {
  CFX5::IO::Data::FREEMEM($_[0]);
}

=head1 NAME

CFX5::IO::Base - Low-level Perl access to the CFX-5 IO library

=head1 SYNOPSIS

  use CFX5::IO::Data;

=head1 DESCRIPTION

This module implements the low-level access to the data structure for
the CFX-5 IO library from perl, and is used by L<CFX5::IO> to access
CFX-5 definition and results files.  It should never have to be used
directly, but that is no excuse for the lack of documentation ...

=head1 AUTHOR

Andy Mortimer <andy.mortimer@aeat.com>

=head1 SEE ALSO

L<CFX5::IO::Base>
L<CFX5::IO>

=head2 new

  $data=new CFX5::IO::Data();

Returns a fresh new CFX5::IO::Data object, just ready to be passed
into the IO library.

=cut

=head2 char

  $var=$data->char();
  $data->char('hello.def');

Sets or gets the char array.

=cut

sub char {
  my $self=shift;
  my $old=$self->GETCHAR();
  if (@_) {
    if (defined $_[0]) {
      # set it
      $self->SETCHAR($_[0]);
    } else {
      # clear it
      $self->ALLOCARRAY(IOP_DATARR_CHAR,0);
    }
  }
  $old;
}

=head2 attribute arrays

All the arrays except the char array -- which is a single string! --
are treated the same by this module.  The following array names
(I<attr> in the following discussion) are used:

=over

=item string

Perl string value, maximum 80 characters.

=item intr

Perl integer value.

=item real

Perl floating point value.

=item dble

Perl floating point value.

=item logl

???

=item offset

Not yet usable.

=back

=head3 numI<attr>

  $num=$data->numattr();
  $data->numattr(10);

The first form returns a count of the number of attributes I<attr>
associated with the object.  The second form sets this number, and
also ensures that the correct amount of memory is allocated internally
for the array; this can be used to preextend the array before making
calls which want to write data into it.

=cut

sub _numattr {
  my $self=shift;
  my $pos=shift;
  my $num=$self->GETCOUNT($pos);
  if (@_) {
    $self->ALLOCARRAY($pos,$_[0]);
  }
  $num;
}

sub numoffset {
  my $self=shift;
  $self->_numattr(IOP_DATARR_OFFSET,@_);
}

sub numstring {
  my $self=shift;
  $self->_numattr(IOP_DATARR_STRING,@_);
}

sub numintr {
  my $self=shift;
  $self->_numattr(IOP_DATARR_INTR,@_);
}

sub numreal {
  my $self=shift;
  $self->_numattr(IOP_DATARR_REAL,@_);
}

sub numdble {
  my $self=shift;
  $self->_numattr(IOP_DATARR_DBLE,@_);
}

sub numlogl {
  my $self=shift;
  $self->_numattr(IOP_DATARR_LOGL,@_);
}

=head3 I<attr>elt

  $elt=$data->attrelt(0);
  $data->attrelt(0,'hello');

Gets or sets one element in the list of attributes.  The first number
is the location in the array, and the second element (if specified) is
the new value.  The type required for this value depends on the
attribute being set.

=cut

sub stringelt {
  my $self=shift;
  my $num=shift;
  my $old=$self->GETSTRING($num);
  if (@_) {
    $self->SETSTRING($num,$_[0]);
  }
  $old;
}

sub intrelt {
  my $self=shift;
  my $num=shift;
  my $old=$self->GETINTR($num);
  if (@_) {
    $self->SETINTR($num,$_[0]);
  }
  $old;
}

sub offsetelt {
  my $self=shift;
  my $num=shift;
  my $old=$self->GETOFFSET($num);
  if (@_) {
    $self->SETOFFSET($num,$_[0]);
  }
  $old;
}

sub realelt {
  my $self=shift;
  my $num=shift;
  my $old=$self->GETREAL($num);
  if (@_) {
    $self->SETREAL($num,$_[0]);
  }
  $old;
}

sub dbleelt {
  my $self=shift;
  my $num=shift;
  my $old=$self->GETDBLE($num);
  if (@_) {
    $self->SETDBLE($num,$_[0]);
  }
  $old;
}

=head3 _resetmemory

Some IO module routines, if they run out of data, pass the required
sizes back in the C<num*> elements of the data structure and expect
the application to re-allocate the memory and try again.  This
convenience function ensures that the memory allocated for each array
is as required by the count for that array.

=cut

sub _resetmemory {
  my $self=shift;

  for my $type (IOP_DATARR_OFFSET(), IOP_DATARR_STRING(),
		IOP_DATARR_CHAR(), IOP_DATARR_INTR(),
		IOP_DATARR_REAL(), IOP_DATARR_DBLE(),
		IOP_DATARR_LOGL()) {
    $self->REALLOCARRAY($type);
  }

  1;
}

=head2 dump

  print $data->dump();

Returns a string summarising the contents.  Not more than 10 items
from any class will be displayed, as it is mostly for debugging.

=cut

sub dump {
  my $self=shift;
  my @rv;
  my $c;

  for my $t (qw(offset string intr real dble logl)) {
    my $rtn="num$t";
    push @rv, "  ". ($c=$self->$rtn()). " ${t}s\n";
    if ($c) {
      $rtn="${t}elt";
      for (my $i=0; $i<$c and $i<7; $i++) {
	push @rv, "    * ". $self->$rtn($i)."\n";
      }
      if ($c > 7) {
	push @rv, "    * ...\n";
      }
    }
  }

  push @rv, "  char = ", (defined $self->char() ? $self->char() : '""') ,"\n";

  join('',@rv);
}

1;

__END__
