Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.2 KiB

  1. package File::Compare;
  2. use strict;
  3. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $Too_Big *FROM *TO);
  4. require Exporter;
  5. use Carp;
  6. $VERSION = '1.1002';
  7. @ISA = qw(Exporter);
  8. @EXPORT = qw(compare);
  9. @EXPORT_OK = qw(cmp compare_text);
  10. $Too_Big = 1024 * 1024 * 2;
  11. sub VERSION {
  12. # Version of File::Compare
  13. return $File::Compare::VERSION;
  14. }
  15. sub compare {
  16. croak("Usage: compare( file1, file2 [, buffersize]) ")
  17. unless(@_ == 2 || @_ == 3);
  18. my ($from,$to,$size) = @_;
  19. my $text_mode = defined($size) && (ref($size) eq 'CODE' || $size < 0);
  20. my ($fromsize,$closefrom,$closeto);
  21. local (*FROM, *TO);
  22. croak("from undefined") unless (defined $from);
  23. croak("to undefined") unless (defined $to);
  24. if (ref($from) &&
  25. (UNIVERSAL::isa($from,'GLOB') || UNIVERSAL::isa($from,'IO::Handle'))) {
  26. *FROM = *$from;
  27. } elsif (ref(\$from) eq 'GLOB') {
  28. *FROM = $from;
  29. } else {
  30. open(FROM,"<$from") or goto fail_open1;
  31. unless ($text_mode) {
  32. binmode FROM;
  33. $fromsize = -s FROM;
  34. }
  35. $closefrom = 1;
  36. }
  37. if (ref($to) &&
  38. (UNIVERSAL::isa($to,'GLOB') || UNIVERSAL::isa($to,'IO::Handle'))) {
  39. *TO = *$to;
  40. } elsif (ref(\$to) eq 'GLOB') {
  41. *TO = $to;
  42. } else {
  43. open(TO,"<$to") or goto fail_open2;
  44. binmode TO unless $text_mode;
  45. $closeto = 1;
  46. }
  47. if (!$text_mode && $closefrom && $closeto) {
  48. # If both are opened files we know they differ if their size differ
  49. goto fail_inner if $fromsize != -s TO;
  50. }
  51. if ($text_mode) {
  52. local $/ = "\n";
  53. my ($fline,$tline);
  54. while (defined($fline = <FROM>)) {
  55. goto fail_inner unless defined($tline = <TO>);
  56. if (ref $size) {
  57. # $size contains ref to comparison function
  58. goto fail_inner if &$size($fline, $tline);
  59. } else {
  60. goto fail_inner if $fline ne $tline;
  61. }
  62. }
  63. goto fail_inner if defined($tline = <TO>);
  64. }
  65. else {
  66. unless (defined($size) && $size > 0) {
  67. $size = $fromsize;
  68. $size = 1024 if $size < 512;
  69. $size = $Too_Big if $size > $Too_Big;
  70. }
  71. my ($fr,$tr,$fbuf,$tbuf);
  72. $fbuf = $tbuf = '';
  73. while(defined($fr = read(FROM,$fbuf,$size)) && $fr > 0) {
  74. unless (defined($tr = read(TO,$tbuf,$fr)) && $tbuf eq $fbuf) {
  75. goto fail_inner;
  76. }
  77. }
  78. goto fail_inner if defined($tr = read(TO,$tbuf,$size)) && $tr > 0;
  79. }
  80. close(TO) || goto fail_open2 if $closeto;
  81. close(FROM) || goto fail_open1 if $closefrom;
  82. return 0;
  83. # All of these contortions try to preserve error messages...
  84. fail_inner:
  85. close(TO) || goto fail_open2 if $closeto;
  86. close(FROM) || goto fail_open1 if $closefrom;
  87. return 1;
  88. fail_open2:
  89. if ($closefrom) {
  90. my $status = $!;
  91. $! = 0;
  92. close FROM;
  93. $! = $status unless $!;
  94. }
  95. fail_open1:
  96. return -1;
  97. }
  98. *cmp = \&compare;
  99. sub compare_text {
  100. my ($from,$to,$cmp) = @_;
  101. croak("Usage: compare_text( file1, file2 [, cmp-function])")
  102. unless @_ == 2 || @_ == 3;
  103. croak("Third arg to compare_text() function must be a code reference")
  104. if @_ == 3 && ref($cmp) ne 'CODE';
  105. # Using a negative buffer size puts compare into text_mode too
  106. $cmp = -1 unless defined $cmp;
  107. compare($from, $to, $cmp);
  108. }
  109. 1;
  110. __END__
  111. =head1 NAME
  112. File::Compare - Compare files or filehandles
  113. =head1 SYNOPSIS
  114. use File::Compare;
  115. if (compare("file1","file2") == 0) {
  116. print "They're equal\n";
  117. }
  118. =head1 DESCRIPTION
  119. The File::Compare::compare function compares the contents of two
  120. sources, each of which can be a file or a file handle. It is exported
  121. from File::Compare by default.
  122. File::Compare::cmp is a synonym for File::Compare::compare. It is
  123. exported from File::Compare only by request.
  124. File::Compare::compare_text does a line by line comparison of the two
  125. files. It stops as soon as a difference is detected. compare_text()
  126. accepts an optional third argument: This must be a CODE reference to
  127. a line comparison function, which returns 0 when both lines are considered
  128. equal. For example:
  129. compare_text($file1, $file2)
  130. is basically equivalent to
  131. compare_text($file1, $file2, sub {$_[0] ne $_[1]} )
  132. =head1 RETURN
  133. File::Compare::compare return 0 if the files are equal, 1 if the
  134. files are unequal, or -1 if an error was encountered.
  135. =head1 AUTHOR
  136. File::Compare was written by Nick Ing-Simmons.
  137. Its original documentation was written by Chip Salzenberg.
  138. =cut