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.

75 lines
1.5 KiB

  1. package Search::Dict;
  2. require 5.000;
  3. require Exporter;
  4. @ISA = qw(Exporter);
  5. @EXPORT = qw(look);
  6. =head1 NAME
  7. Search::Dict, look - search for key in dictionary file
  8. =head1 SYNOPSIS
  9. use Search::Dict;
  10. look *FILEHANDLE, $key, $dict, $fold;
  11. =head1 DESCRIPTION
  12. Sets file position in FILEHANDLE to be first line greater than or equal
  13. (stringwise) to I<$key>. Returns the new file position, or -1 if an error
  14. occurs.
  15. The flags specify dictionary order and case folding:
  16. If I<$dict> is true, search by dictionary order (ignore anything but word
  17. characters and whitespace).
  18. If I<$fold> is true, ignore case.
  19. =cut
  20. sub look {
  21. local(*FH,$key,$dict,$fold) = @_;
  22. local($_);
  23. my(@stat) = stat(FH)
  24. or return -1;
  25. my($size, $blksize) = @stat[7,11];
  26. $blksize ||= 8192;
  27. $key =~ s/[^\w\s]//g if $dict;
  28. $key = lc $key if $fold;
  29. my($min, $max, $mid) = (0, int($size / $blksize));
  30. while ($max - $min > 1) {
  31. $mid = int(($max + $min) / 2);
  32. seek(FH, $mid * $blksize, 0)
  33. or return -1;
  34. <FH> if $mid; # probably a partial line
  35. $_ = <FH>;
  36. chop;
  37. s/[^\w\s]//g if $dict;
  38. $_ = lc $_ if $fold;
  39. if (defined($_) && $_ lt $key) {
  40. $min = $mid;
  41. }
  42. else {
  43. $max = $mid;
  44. }
  45. }
  46. $min *= $blksize;
  47. seek(FH,$min,0)
  48. or return -1;
  49. <FH> if $min;
  50. for (;;) {
  51. $min = tell(FH);
  52. defined($_ = <FH>)
  53. or last;
  54. chop;
  55. s/[^\w\s]//g if $dict;
  56. $_ = lc $_ if $fold;
  57. last if $_ ge $key;
  58. }
  59. seek(FH,$min,0);
  60. $min;
  61. }
  62. 1;