[system] / trunk / pg / lib / WeBWorK / EquationCache.pm Repository:
ViewVC logotype

View of /trunk/pg/lib/WeBWorK/EquationCache.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3291 - (download) (as text) (annotate)
Wed Jun 15 22:00:32 2005 UTC (14 years, 8 months ago) by jj
File size: 3116 byte(s)
Changed whitespace removal of TeX strings to safer version.

    1 ################################################################################
    2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
    3 # $Id$
    4 ################################################################################
    5 
    6 package WeBWorK::EquationCache;
    7 
    8 =head1 NAME
    9 
   10 WeBWorK::EquationCache - create and cache images of TeX equations.
   11 
   12 =head1 SYNPOSIS
   13 
   14  my $cache = WeBWorK::EquationCache->new(cacheDB => "/path/to/equationcache.db");
   15  my $imageName = $cache->lookup('\[3x^2\]');
   16 
   17 =head1 DESCRIPTION
   18 
   19 WeBWorK::PG::EquationCache maintains a list of unique identifiers for TeX
   20 strings. The unique identifier is based on an MD5 hash of the TeX string, and a
   21 sequence number. Before calcuating the MD5 hash of a TeX string, all whitespace
   22 is removed.
   23 
   24 =head2 FILE FORMAT
   25 
   26 The cache database file is a text file consisting of lines of the following
   27 form:
   28 
   29  md5_hash     sequence_number     tex_string
   30 
   31 Any amount of whitespace may separate the fields. Lines which do not conform to
   32 this format are ignored. Any string of characters beginning with `#' and
   33 extending to the end of the line is also ignored.
   34 
   35 =cut
   36 
   37 use strict;
   38 use warnings;
   39 use Digest::MD5 qw(md5_hex);
   40 use Fcntl qw(:DEFAULT :flock);
   41 BEGIN { O_RDWR; O_CREAT; LOCK_EX } # get rid of "subroutine redefined" warnings
   42 
   43 =head1 METHODS
   44 
   45 =over
   46 
   47 =item new(%options)
   48 
   49 Returns a new EquationCache object. C<%options> must contain the following
   50 entries:
   51 
   52  cacheDB => path to image cache database file
   53 
   54 If cacheDB is the empty string, don't use a cache file and assume that there
   55 are no md5 collisions.
   56 
   57 =cut
   58 
   59 sub new {
   60   my ($invocant, %options) = @_;
   61   my $class = ref $invocant || $invocant;
   62   my $self = {
   63     %options,
   64   };
   65 
   66   bless $self, $class;
   67 }
   68 
   69 =item lookup
   70 
   71 Looks up a TeX string in the database. A unique identifier for the cached image
   72 is returned. If necessary, the string is added to the database.
   73 
   74 =cut
   75 
   76 sub lookup {
   77   my ($self, $tex) = @_;
   78   # There are several ways to normalize TeX strings.  Use only
   79   # one of them.
   80 
   81   # Option 1 (default): remove leading and trailing whitespace, and
   82   # compress all other whitespace to single spaces.
   83   $tex =~ s/^\s+//g;
   84   $tex =~ s/\s+$//g;
   85   $tex =~ s/\s+/ /g;
   86   # Option 2 (the old default): remove all whitespace
   87   # $tex =~ s/\s+//g;
   88 
   89   my $md5 = md5_hex($tex);
   90 
   91   my $db = $self->{cacheDB};
   92   unless($db) { return($md5 ."1"); }
   93   sysopen(DB, $db, O_RDWR|O_CREAT)
   94     or die "failed to create/open cacheDB $db: $!";
   95   flock(DB, LOCK_EX)
   96     or die "failed to write-lock cacheDB $db: $!";
   97 
   98   my $line = 0;
   99   my $max = 0;
  100   my $match = 0;
  101   local $/ = "\n";
  102   while (<DB>) {
  103     # find matching MD5 hashes
  104     next unless m/^$md5\s+(\d+)\s+(.*)$/;
  105     if ($tex = $2) {
  106       # the TeX string matches: use this instance number and stop looking
  107       $match = $1;
  108       last;
  109     } else {
  110       # the TeX string doesn't match: record instance number and keep looking
  111       $max = $1 if $1 > $max;
  112     }
  113   }
  114 
  115   unless ($match) {
  116     # no match: invent a new instance number and add TeX string to DB
  117     $match = $max + 1;
  118     seek(DB, 0, 2); # we should already be at EOF, but what the hell.
  119     print DB "$md5\t$match\t$tex\n";
  120   }
  121 
  122   close(DB);
  123   return "$md5$match";
  124 }
  125 
  126 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9