Leaked source code of windows server 2003
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.

182 lines
4.4 KiB

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