File: Version.pm

package info (click to toggle)
libpandoc-wrapper-perl 0.9.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 304 kB
  • sloc: perl: 589; makefile: 5; sh: 1
file content (180 lines) | stat: -rw-r--r-- 4,639 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package Pandoc::Version;
use 5.014;
use warnings;

our $VERSION = '0.9.2';

use overload
  '""'     => 'string',
  '0+'     => 'number',
  cmp      => 'cmp',
  '<=>'    => 'cmp',
  fallback => 1;
use Scalar::Util qw(reftype blessed);
use Pandoc::Error;

our @CARP_NOT = ('Pandoc');

sub new {
    my $class = shift;

    # We accept array or string input
    # (or mixed but let's not document that!)
    my @nums =
      map {
        my $num = $_;
        $num =~ /^\d+$/
          or Pandoc::Error->throw(
            message => 'invalid version number',
            version => $num
          );
        $num =~ s/^0+(?=\d)//;    # ensure decimal interpretation
        $num = 0 + $num;
        $num
      }
      map { s/^v//i; split /\./ }    ## no critic
      map { 'ARRAY' CORE::eq ( reftype $_ // "" ) ? @$_ : $_ }
      map { $_ // '' } @_;

    Pandoc::Error->throw('invalid version number') unless @nums;

    return bless \@nums => $class;
}

sub string { join '.', @{ $_[0] } }

sub number {
    my ( $major, @minors ) = @{ $_[0] };
    no warnings qw(uninitialized numeric);
    if (@minors) {
        my $minor = join '', map { sprintf '%03d', $_ } @minors;
        return 0 + "$major.$minor";    # return a true number
    }
    return 0 + $major;
}

sub cmp {
    my ( $a, $b ) = map {
        ( blessed $_ and $_->isa('Pandoc::Version') )
          ? $_
          : Pandoc::Version->new( $_ // () )
    } ( $_[0], $_[1] );
    return $a->number <=> $b->number;
}

sub match {
    my ( $a, $b ) = map { Pandoc::Version->new($_) } @_;
    pop @$a while @$a > @$b;
    pop @$b while @$b > @$a;

    return $a->number == $b->number;
}

my %cmp_truth_table = (
    '==' => [ 0, 1, 0 ],
    '!=' => [ 1, 0, 1 ],
    '>=' => [ 0, 1, 1 ],
    '<=' => [ 1, 1, 0 ],
    '<'  => [ 1, 0, 0 ],
    '>'  => [ 0, 0, 1 ]
);

sub fulfills {
    my ( $self, $req ) = @_;
    return 1 unless $req;

    my @parts = split qr{\s*,\s*}, $req;
    for my $part (@parts) {
        my ( $op, $ver ) =
          $part =~ m{^\s*(==|>=|>|<=|<|!=)?\s*v?(\d+(\.\d+)*)$};
        if ( !defined $ver ) {
            Pandoc::Error->throw(
                message => "invalid version requirement: $req",
                require => $req,
            );
        }

        my $cmp = $self->cmp($ver) + 1;    # will be 0 for <, 1 for ==, 2 for >
        return unless $cmp_truth_table{ $op || '>=' }->[$cmp];
    }

    1;
}

sub TO_JSON {
    my ($self) = @_;
    return [ map { 0 + $_ } @$self ];
}

1;

__END__

=head1 NAME

Pandoc::Version - version number of pandoc and its libraries

=head1 SYNOPSIS

  $version = Pandoc::Version->new("1.17.2");     # create version
  $version = bless [1,17,2], 'Pandoc::Version';  # equivalent

  "$version";       # stringify to "1.17.2"
  $version > 1.9;   # compare
  $version->[0];    # major
  $version->[1];    # minor

  $version->match('1.17');   # true for 1.17, 1.17.x, 1.17.x.y...

=head1 DESCRIPTION

This module is used to store and compare version numbers of pandoc executable
and Haskell libraries compiled into pandoc. A Pandoc::Version object is an
array reference of one or more non-negative integer values.

In most cases there is no need to create Pandoc::Version objects by hand. Just
use the instances returned by methods C<version> and C<libs> of module
L<Pandoc> and trust in overloading.

=head1 METHODS

=head2 string

Return a string representation of a version, for instance C<"1.17.0.4">. This
method is automatically called by overloading in string context.

=head2 number

Return a number representation of a version, for instance C<1.017000004>. This
method is automatically called by overloading in number context.

=head2 cmp( $version )

Compare two version numbers. This is method is used automatically by
overloading to compare version objects with strings or numbers (operators
C<eq>, C<lt>, C<le>, C<ge>, C<==>, C<< < >>, C<< > >>, C<< <= >>, and C<< >=
>>).

=head2 match( $version )

Return whether a version number matches another version number if cut to the
same number of parts. For instance C<1.2.3> matches C<1>, C<1.2>, and C<1.2.3>.

=head2 fulfills( $version_requirement )

Return whether a version number fullfills a version requirement, such as
C<!=1.16, <=1.17>. See L<CPAN::Meta::Spec/Version Ranges> for possible values.

=head2 TO_JSON

Return an array reference of the version number to serialize in JSON format.

=head1 SEE ALSO

L<version> is a similar module for Perl version numbers.

L<SemVer> extends versions to Semantic Versioning as described at L<http://semver.org/>.

L<Pandoc::Release> to get information about and download pandoc releases.

=cut