File Coverage

blib/lib/JCAMP/DX.pm
Criterion Covered Total %
statement 72 74 97.3
branch 29 32 90.6
condition 7 9 77.7
subroutine 10 11 90.9
pod 0 8 0.0
total 118 134 88.0


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             #$Author: andrius $
3             #$Date: 2021-02-10 13:41:55 +0200 (Tr, 10 vas. 2021) $
4             #$Revision: 91 $
5             #$URL: svn+ssh://www.crystallography.net/home/coder/svn-repositories/JCAMP-DX/tags/v0.03/lib/JCAMP/DX.pm $
6             #------------------------------------------------------------------------------
7             #*
8             # Parser for JCAMP-DX format.
9             #**
10              
11             package JCAMP::DX;
12              
13 4     4   17939 use strict;
  4         34  
  4         117  
14 4     4   22 use warnings;
  4         7  
  4         166  
15              
16             # ABSTRACT: parser for JCAMP-DX format
17             our $VERSION = '0.03'; # VERSION
18              
19 4     4   1776 use JCAMP::DX::LabelDataRecord;
  4         10  
  4         3817  
20              
21             sub new
22             {
23 19     19 0 44 my( $class, $title ) = @_;
24 19         81 my $self = bless {
25             labels => [],
26             data => {},
27             blocks => [],
28             }, $class;
29              
30 19 100       47 if( $title ) {
31 2         7 $self->push_LDR( JCAMP::DX::LabelDataRecord->new( 'TITLE', $title ) );
32             }
33              
34 19         39 return $self;
35             }
36              
37             sub new_from_file
38             {
39 10     10 0 4493 my( $class, $filename, $options ) = @_;
40 10         340 open( my $inp, $filename );
41              
42 10 100       55 ${$options->{store_file}} = '' if $options->{store_file};
  5         13  
43              
44 10         186 my $title = <$inp>;
45 10 100       37 ${$options->{store_file}} .= $title if $options->{store_file};
  5         12  
46 10         65 $title =~ s/^\s*##title=//i;
47 10         45 $title =~ s/\r?\n$//;
48              
49 10         51 my $block = $class->new_from_fh( $inp, $title, $options );
50              
51 10         128 close $inp;
52 10         214 return $block;
53             }
54              
55             sub new_from_fh
56             {
57 16     16 0 71 my( $class, $inp, $title, $options ) = @_;
58 16         36 my $block = $class->new();
59 16         32 my( $last_label, $buffer ) = ( 'title', $title );
60 16         51 while( my $line = <$inp> ) {
61 268 100       514 ${$options->{store_file}} .= $line if $options->{store_file};
  134         274  
62 268         485 $line =~ s/\$\$.*$//; # removing comments
63 268         916 $line =~ s/\r?\n$//; # removing newlines
64 268 100       701 next if $line =~ /^\s*$/;
65 260 100       537 last if $line =~ /^\s*##end=/i;
66 244 100       802 if( $line =~ s/^\s*##title=//i ) {
    100          
    50          
67 6 100 66     19 if( defined $last_label && $last_label ne '' ) {
68 2         8 $block->push_LDR(
69             JCAMP::DX::LabelDataRecord->new( $last_label, $buffer )
70             );
71 2         4 undef $last_label;
72 2         5 undef $buffer;
73             }
74 6         20 $block->push_block( $class->new_from_fh( $inp, $line, $options ) );
75             } elsif( $line =~ /^\s*##([^=]*)=(.*)$/ ) {
76 112 100 66     376 if( defined $last_label && $last_label ne '' ) {
77 108         277 $block->push_LDR(
78             JCAMP::DX::LabelDataRecord->new( $last_label, $buffer )
79             );
80             }
81 112         516 ( $last_label, $buffer ) = ( $1, $2 );
82             } elsif( $block->{labels} ) {
83 126         364 $buffer .= "\n$line";
84             }
85             }
86              
87 16 100 100     71 if( defined $last_label && $last_label ne '' ) {
88 12         40 $block->push_LDR(
89             JCAMP::DX::LabelDataRecord->new( $last_label, $buffer )
90             );
91             }
92              
93 16         43 return $block;
94             }
95              
96             sub push_block
97             {
98 6     6 0 11 my( $self, $block ) = @_;
99 6         9 push @{$self->{blocks}}, $block;
  6         25  
100             }
101              
102             sub push_LDR
103             {
104 132     132 0 372 my( $self, $ldr ) = @_;
105              
106 132 100       285 if( exists $self->{data}{$ldr->canonical_label} ) {
107 2         5 warn "duplicate values for label '" . $ldr->canonical_label .
108             "' were found, will not overwrite";
109 2         169 return;
110             }
111              
112 130         212 push @{$self->{labels}}, $ldr;
  130         258  
113 130         290 $self->{data}{$ldr->canonical_label} = $ldr;
114             }
115              
116             sub title
117             {
118 0     0 0 0 return $_[0]->{data}{TITLE}->value;
119             }
120              
121             sub order_labels
122             {
123 1     1 0 2 my( $self ) = @_;
124              
125             $self->{labels} = [
126             (exists $self->{data}{TITLE} ? $self->{data}{TITLE} : () ),
127             (exists $self->{data}{JCAMPDX} ? $self->{data}{JCAMPDX} : () ),
128 3 100       22 grep { $_->label ne 'TITLE' && $_->label ne 'JCAMP-DX' }
129 1 50       6 @{$self->{labels}} ];
  1 50       25  
130             }
131              
132             sub to_string
133             {
134 3     3 0 347 my( $self ) = @_;
135 3         6 my $output = '';
136              
137 3         6 for my $label (@{$self->{labels}}) {
  3         8  
138 8         22 $output .= $label->to_string;
139             }
140              
141 3         5 for my $block (@{$self->{blocks}}) {
  3         7  
142 0         0 $output .= $block->to_string;
143             }
144              
145 3         6 $output .= "##END=\n";
146 3         13 return $output;
147             }
148              
149             1;