#------------------------------------------------------------------------------ #$Author: andrius $ #$Date: 2021-02-10 13:41:55 +0200 (Tr, 10 vas. 2021) $ #$Revision: 91 $ #$URL: svn+ssh://www.crystallography.net/home/coder/svn-repositories/JCAMP-DX/tags/v0.03/lib/JCAMP/DX.pm $ #------------------------------------------------------------------------------ #* # Parser for JCAMP-DX format. #** package JCAMP::DX; use strict; use warnings; # ABSTRACT: parser for JCAMP-DX format our $VERSION = '0.03'; # VERSION use JCAMP::DX::LabelDataRecord; sub new { my( $class, $title ) = @_; my $self = bless { labels => [], data => {}, blocks => [], }, $class; if( $title ) { $self->push_LDR( JCAMP::DX::LabelDataRecord->new( 'TITLE', $title ) ); } return $self; } sub new_from_file { my( $class, $filename, $options ) = @_; open( my $inp, $filename ); ${$options->{store_file}} = '' if $options->{store_file}; my $title = <$inp>; ${$options->{store_file}} .= $title if $options->{store_file}; $title =~ s/^\s*##title=//i; $title =~ s/\r?\n$//; my $block = $class->new_from_fh( $inp, $title, $options ); close $inp; return $block; } sub new_from_fh { my( $class, $inp, $title, $options ) = @_; my $block = $class->new(); my( $last_label, $buffer ) = ( 'title', $title ); while( my $line = <$inp> ) { ${$options->{store_file}} .= $line if $options->{store_file}; $line =~ s/\$\$.*$//; # removing comments $line =~ s/\r?\n$//; # removing newlines next if $line =~ /^\s*$/; last if $line =~ /^\s*##end=/i; if( $line =~ s/^\s*##title=//i ) { if( defined $last_label && $last_label ne '' ) { $block->push_LDR( JCAMP::DX::LabelDataRecord->new( $last_label, $buffer ) ); undef $last_label; undef $buffer; } $block->push_block( $class->new_from_fh( $inp, $line, $options ) ); } elsif( $line =~ /^\s*##([^=]*)=(.*)$/ ) { if( defined $last_label && $last_label ne '' ) { $block->push_LDR( JCAMP::DX::LabelDataRecord->new( $last_label, $buffer ) ); } ( $last_label, $buffer ) = ( $1, $2 ); } elsif( $block->{labels} ) { $buffer .= "\n$line"; } } if( defined $last_label && $last_label ne '' ) { $block->push_LDR( JCAMP::DX::LabelDataRecord->new( $last_label, $buffer ) ); } return $block; } sub push_block { my( $self, $block ) = @_; push @{$self->{blocks}}, $block; } sub push_LDR { my( $self, $ldr ) = @_; if( exists $self->{data}{$ldr->canonical_label} ) { warn "duplicate values for label '" . $ldr->canonical_label . "' were found, will not overwrite"; return; } push @{$self->{labels}}, $ldr; $self->{data}{$ldr->canonical_label} = $ldr; } sub title { return $_[0]->{data}{TITLE}->value; } sub order_labels { my( $self ) = @_; $self->{labels} = [ (exists $self->{data}{TITLE} ? $self->{data}{TITLE} : () ), (exists $self->{data}{JCAMPDX} ? $self->{data}{JCAMPDX} : () ), grep { $_->label ne 'TITLE' && $_->label ne 'JCAMP-DX' } @{$self->{labels}} ]; } sub to_string { my( $self ) = @_; my $output = ''; for my $label (@{$self->{labels}}) { $output .= $label->to_string; } for my $block (@{$self->{blocks}}) { $output .= $block->to_string; } $output .= "##END=\n"; return $output; } 1;