Skip to content

Commit b968a92

Browse files
author
Andrew Allen
committed
fix sv_undef -> PL_sv_undef so it will build in modern perl5's, fix docs
1 parent b7e003d commit b968a92

File tree

7 files changed

+215
-2
lines changed

7 files changed

+215
-2
lines changed

Changes

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Revision history for Perl extension String::DiffLine.
2+
3+
0.01 2000-01-28
4+
- original version; created by h2xs 1.18
5+
6+
0.02 2000-01-31
7+
- updated docs with identical-string return values
8+
9+
0.03 2016-03-27
10+
- fix sv_undef -> PL_sv_undef to build in modern perl5's, fix docs

DiffLine.pm

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package String::DiffLine;
2+
3+
use strict;
4+
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
5+
6+
require Exporter;
7+
require DynaLoader;
8+
require AutoLoader;
9+
10+
@ISA = qw(Exporter DynaLoader);
11+
12+
@EXPORT = qw();
13+
14+
@EXPORT_OK=qw(diffline);
15+
16+
$VERSION = '0.03';
17+
18+
bootstrap String::DiffLine $VERSION;
19+
20+
# Preloaded methods go here.
21+
22+
# Autoload methods go after =cut, and are processed by the autosplit program.
23+
24+
1;
25+
__END__
26+
27+
=head1 NAME
28+
29+
String::DiffLine - find the character, line, and line position of the first difference in two strings
30+
31+
=head1 SYNOPSIS
32+
33+
use String::DiffLine qw(diffline);
34+
($char,$line,$lpos)=diffline("abc","abx");
35+
36+
=head1 DESCRIPTION
37+
38+
=over
39+
40+
=item diffline($str1,$str2)
41+
42+
Returns a three-item list identifying the location of the first
43+
difference between the two strings: the character position (indexed
44+
from 0), the line number (indexed from 1), and the character position
45+
in the current line of the first difference (indexed from 0).
46+
L<perlvar/"$E<sol>"> is used as the line separator.
47+
48+
If the strings are identical, the returned list's first element is C<undef>,
49+
its second element is the number of lines in the string (i.e., the number of
50+
line separators plus one), and the last element is the number of characters
51+
following the last line separator.
52+
53+
=back
54+
55+
=head1 AUTHOR
56+
57+
Andrew Allen <andrew_d_allen (at) hotmail.com>
58+
59+
=head1 SEE ALSO
60+
61+
perl(1).
62+
63+
=cut

DiffLine.xs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifdef __cplusplus
2+
extern "C" {
3+
#endif
4+
#include "EXTERN.h"
5+
#include "perl.h"
6+
#include "XSUB.h"
7+
#ifdef __cplusplus
8+
}
9+
#endif
10+
11+
12+
MODULE = String::DiffLine PACKAGE = String::DiffLine
13+
14+
PROTOTYPES: ENABLE
15+
16+
void
17+
diffline(s1,s2)
18+
char *s1;
19+
char *s2;
20+
PREINIT:
21+
STRLEN l,l1,l2,nll,i,lpos,lines;
22+
char *nl,lnl;
23+
PPCODE:
24+
l1=SvCUR(ST(0));
25+
l2=SvCUR(ST(1));
26+
nl=SvPV(perl_get_sv("/",FALSE),nll);
27+
if(nll==0) nl="\n";
28+
lnl=nl[nll?nll-1:0];
29+
lpos=0;lines=1;
30+
EXTEND(sp,3);
31+
/*printf("s1=%s l1=%d s2=%s l2=%d nl=%s nll=%d\n",s1,l1,s2,l2,nl,nll);*/
32+
l=l1<l2?l1:l2;
33+
for(i=0;i<l;i++)
34+
{
35+
if(s1[i]!=s2[i])
36+
{
37+
PUSHs(sv_2mortal(newSViv(i)));
38+
PUSHs(sv_2mortal(newSViv(lines)));
39+
PUSHs(sv_2mortal(newSViv(i-lpos)));
40+
XSRETURN(3);
41+
}
42+
/* check if we're at last character of end-of-line 'nl' */
43+
if(s1[i]==lnl &&
44+
(nll==1 ||
45+
(nll?i-lpos+1>=nll && memcmp(s1+i-nll+1,nl,nll)==0:
46+
i==l-1 || s1[i+1]!=lnl)))
47+
lines++,lpos=i+1;
48+
}
49+
if(l1==l2)
50+
PUSHs(&PL_sv_undef);
51+
else
52+
PUSHs(sv_2mortal(newSViv(l)));
53+
PUSHs(sv_2mortal(newSViv(lines)));
54+
PUSHs(sv_2mortal(newSViv(i-lpos)));
55+
56+

MANIFEST

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Changes
2+
DiffLine.pm
3+
DiffLine.xs
4+
MANIFEST
5+
Makefile.PL
6+
test.pl
7+
README.md

Makefile.PL

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use ExtUtils::MakeMaker;
2+
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
3+
# the contents of the Makefile that is written.
4+
WriteMakefile(
5+
'NAME' => 'String::DiffLine',
6+
'VERSION_FROM' => 'DiffLine.pm', # finds $VERSION
7+
'LIBS' => [''], # e.g., '-lm'
8+
'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
9+
'INC' => '', # e.g., '-I/usr/include/other'
10+
);

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
1-
# String-DiffLine
2-
perl5 module to find the character, line, and line position of the first difference in two strings
1+
# String::DiffLine
2+
perl5 module to find the character, line, and line position of the first difference in two strings,
3+
written in perlxs/C for speed
4+
5+
# DESCRIPTION
6+
String::DiffLine defines a C/perlxs function "diffline" which finds the
7+
character position, line number, and line character position of
8+
the first difference in two strings quickly. See POD documentation for more details
9+
10+
# INSTALLATION
11+
To install this module use the cpan perl installer script: `cpan String::Diffline`,
12+
the CPAN perl module: `perl -MCPAN -e 'install(q{String::DiffLine})'`
13+
or if you like the hard way:
14+
```bash
15+
perl Makefile.PL
16+
make
17+
make test # check for absence of 'not ok' lines
18+
make install
19+
```
20+
21+
# AUTHOR
22+
Andrew Allen, andrew_d_allen (at) hotmail.com

test.pl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Before `make install' is performed this script should be runnable with
2+
# `make test'. After `make install' it should work as `perl test.pl'
3+
4+
######################### We start with some black magic to print on failure.
5+
6+
# Change 1..1 below to 1..last_test_to_print .
7+
# (It may become useful if the test is moved to ./t subdirectory.)
8+
9+
BEGIN { $| = 1; print "1..12\n"; }
10+
END {print "not ok 1\n" unless $loaded;}
11+
use String::DiffLine qw(diffline);
12+
$loaded = 1;
13+
print "ok 1\n";
14+
15+
######################### End of black magic.
16+
17+
# Insert your test code below (better if it prints "ok 13"
18+
# (correspondingly "not ok 13") depending on the success of chunk 13
19+
# of the test code):
20+
21+
my @tests=(
22+
[2 ,sub{}, ["abcdef" ,"abcxyz" ],[3,1,3], ],
23+
[3 ,sub{}, ["abcdef" ,"abc" ],[3,1,3], ],
24+
[4 ,sub{}, ["abc" ,"abc" ],[undef,1,3],],
25+
[5 ,sub{}, ["abc\ndefg" ,"abc\ndxy" ],[5,2,1], ],
26+
[6 ,sub{}, ["abc\n\ndefg" ,"abc\n\ndxy" ],[6,3,1], ],
27+
[7 ,sub{}, ["abc\ndef\n" ,"abc\ndef\n" ],[undef,3,0],],
28+
[8 ,sub{$/="x"}, ["abcxdefg" ,"abcxdefy" ],[7,2,3], ],
29+
[9 ,sub{$/=""} , ["abc\n\n\ndefg","abc\n\n\nxy" ],[6,2,0], ],
30+
[10,sub{$/="121"},["1212121def" ,"1212121dex" ],[9,3,2], ],
31+
[11,sub{$/="112"},["11121112de" ,"11121112df" ],[9,3,1], ],
32+
[12,sub{$/="112"},["112112x" ,"112112ab" ],[6,3,0], ],
33+
);
34+
35+
foreach my $test (@tests)
36+
{
37+
my($n,$s,$in,$tout)=@$test;
38+
&$s;
39+
my(@in2)=@$in;
40+
my $nl=$/;
41+
s/\n/\\n/g foreach ($nl,@in2);
42+
my(@out2)=my(@out)=diffline($in->[0],$in->[1]);
43+
my $fail=grep($_ ne shift @out,@$tout);
44+
local $"=",";
45+
print "\$/=$nl in=@in2 out=@out2 expected=@$tout\n";
46+
printf "%s %d\n",($fail?"not ok":"ok"),$n;
47+
}

0 commit comments

Comments
 (0)