Annotation of loncom/ConfigFileEdit.pm, revision 1.1
1.1 ! foxr 1: #
! 2: #
! 3: #
! 4: # Copyright Michigan State University Board of Trustees
! 5: #
! 6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
! 7: #
! 8: # LON-CAPA is free software; you can redistribute it and/or modify
! 9: # it under the terms of the GNU General Public License as published by
! 10: # the Free Software Foundation; either version 2 of the License, or
! 11: # (at your option) any later version.
! 12: #
! 13: # LON-CAPA is distributed in the hope that it will be useful,
! 14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
! 15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 16: # GNU General Public License for more details.
! 17: #
! 18: # You should have received a copy of the GNU General Public License
! 19: # along with LON-CAPA; if not, write to the Free Software
! 20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 21: #
! 22: # /home/httpd/html/adm/gpl.txt
! 23: #
! 24: # http://www.lon-capa.org/
! 25: #
! 26:
! 27: package ConfigFileEdit;
! 28:
! 29: #
! 30: # Module to read/edit configuration files.
! 31: # See the POD at the bottom of the file for more information.
! 32:
! 33: #------------------------------ internal utility functions ----------
! 34:
! 35: #
! 36: # Comment
! 37: # Returns true if the line is completely a comment.
! 38: # Paramter:
! 39: # line
! 40: # Contents of a configuration file line.
! 41: #
! 42: sub Comment {
! 43: my $line = shift;
! 44:
! 45: # Leading whitespace followed by a #..
! 46:
! 47: if ($line =~ /^[' ',\t]*\#/) {
! 48: return 1;
! 49: }
! 50: # Solely whitespace or empty line.
! 51:
! 52: $line =~ s/[' ',\t]//g;
! 53: return ($line eq "");
! 54:
! 55: }
! 56:
! 57: #
! 58: # Field
! 59: # Return the value of a field in the line. Leading whitespace is trimmed
! 60: # from the first key (key 0).
! 61: # Parameters:
! 62: # line
! 63: # Line from which to extract the field.
! 64: #
! 65: # idx
! 66: # Index of the field to extract.
! 67: #
! 68: sub Field {
! 69: my $line = shift;
! 70: my $idx = shift;
! 71:
! 72: $line =~ s/(^ *)|(^\t*)//;
! 73:
! 74: my @fields = split(/:/, $line);
! 75:
! 76: return $fields[$idx];
! 77: }
! 78: #
! 79: # Index:
! 80: # Return a reference to a hash that indexes a line array.
! 81: # The hash is keyed on a field in the line array lines
! 82: # Each hash entry is the line number of the line in which
! 83: # that key value appears. Note that at present, keys must be
! 84: # unique.
! 85: # Parameters:
! 86: # $array - Reference to a line array.
! 87: # $idxfield - Field number to index on (0 is the first field).
! 88: # Returns:
! 89: # Reference to the index hash:
! 90: sub Index {
! 91: my $array = shift;
! 92: my $idxfield = shift;
! 93:
! 94: my %hash;
! 95: for(my $l = 0; $l < scalar(@$array); $l++) {
! 96: chomp $array->[$l]; # Ensure lines have no \n's.
! 97: my $line = $array->[$l];
! 98: if(!Comment($line)) {
! 99: my $keyvalue = Field($line, $idxfield);
! 100: $hash{$keyvalue} = $l;
! 101: }
! 102: }
! 103:
! 104:
! 105: return \%hash;
! 106: }
! 107:
! 108:
! 109: #------------------------------- public functions --------------------
! 110: #
! 111: # new
! 112: # Create a new configuration file editor object.
! 113: # configuration files are : separated fields that
! 114: # may have comments, blank lines and trailing comments.
! 115: # comments are indicated by #"s.
! 116: # Parameters:
! 117: # filename
! 118: # Name of file to open.
! 119: # indexfield
! 120: # Select the field to index the file by.
! 121: #
! 122: #
! 123: sub new {
! 124: my $class = shift;
! 125: my $filename = shift;
! 126: my $indexfield = shift;
! 127:
! 128: # Open the configuration file. Failure results in the return
! 129: # of an undef.
! 130: # Note we dont' need to hold on to the file handle after the file
! 131: # is read in.
! 132:
! 133: open(CONFIGFILE, "< $filename")
! 134: or return undef;
! 135:
! 136:
! 137: # Read the file into a line array:
! 138:
! 139: my @linearray = <CONFIGFILE>;
! 140: close(CONFIGFILE);
! 141:
! 142:
! 143: # Build the key to lines hash: this hash
! 144: # is keyed on item $indexfield of the line
! 145: # and contains the line number of the actual line.
! 146:
! 147: my $hashref = Index(\@linearray, $indexfield);
! 148:
! 149:
! 150: # Build the object hash, bless it and return.
! 151:
! 152: my $self = { Filename => $filename,
! 153: Indexfield => $indexfield,
! 154: LineArray => \@linearray,
! 155: KeyToLines => $hashref};
! 156:
! 157: bless ($self, $class);
! 158:
! 159: return $self;
! 160:
! 161: }
! 162: #
! 163: # Append an element to the configuration file array.
! 164: # The element is placed at the end of the array. If the element is not
! 165: # a comment. The key is added to the index.
! 166: #
! 167: # Parameters:
! 168: # $self - Reference to our member hash.
! 169: # $line - A line to add to the config file.
! 170: sub Append {
! 171: my $self = shift;
! 172: my $line = shift;
! 173:
! 174: # Regardless, the line is added to the config file.
! 175:
! 176: my $linearray = ($self->{LineArray});
! 177: push(@$linearray, $line); # Append the line.
! 178: my $newindex = @$linearray - 1; # Index of new line.
! 179:
! 180: # If the line is not a comment, pull out the desired field and add
! 181: # it to the line index hash.
! 182:
! 183: if(!Comment($line)) {
! 184: my $field = Field($line, $self->{Indexfield});
! 185: $self->{KeyToLines}->{$field} = $newindex;
! 186: }
! 187: }
! 188: #
! 189: # Find a non comment line by looking it up by key.
! 190: # Parameters:
! 191: # $self - Reference to our member hash.
! 192: # $key - Lookup key.
! 193: # Returns:
! 194: # Contents of the line or undef if there is no match.
! 195: #
! 196: sub Find {
! 197: my $self = shift;
! 198: my $key = shift;
! 199:
! 200: my $hash = $self->{KeyToLines};
! 201: if(defined($hash->{$key})) {
! 202: my $lines = $self->{LineArray};
! 203: return $lines->[$hash->{$key}];
! 204: } else {
! 205: return undef;
! 206: }
! 207: }
! 208: #
! 209: # Return the number of lines in the current configuration file.
! 210: # Note that this count includes the comment lines. To
! 211: # Get the non comment lines the best thing is to iterate through the
! 212: # keys of the KeyToLines hash.
! 213: # Parameters:
! 214: # $self - Reference to member data hash for the object.
! 215: #
! 216: sub LineCount {
! 217: my $self = shift;
! 218: my $lines = $self->{LineArray};
! 219: my $count = @$lines;
! 220: return $count;
! 221: }
! 222: #
! 223: # Delete a line from the configuration file.
! 224: # Note at present, there is no support for deleting comment lines.
! 225: # The line is deleted, from the array. All lines following are slid back
! 226: # one index and the index hash is rebuilt.
! 227: # Parameters:
! 228: # $self - Reference to the member data hash for the object.
! 229: # $key - key value of the line to delete.
! 230: # NOTE:
! 231: # If a line matching this key does not exist, this is a no-op.
! 232: #
! 233: sub DeleteLine {
! 234: my $self = shift;
! 235: my $key = shift;
! 236:
! 237: my $lines = $self->{LineArray};
! 238: my $index = $self->{KeyToLines};
! 239: my $lastidx = $self->LineCount() - 1; # Index of last item.
! 240:
! 241:
! 242: my @temp = @$lines;
! 243:
! 244:
! 245: if(! defined($index->{$key})) { # bail if no match.
! 246: return;
! 247: }
! 248: my $itemno = $index->{$key}; # Index of item to delete.
! 249:
! 250: if ($itemno != $lastidx) { # need to slide and reindex.
! 251: @$temp[$itemno..($lastidx-1)] =
! 252: @$temp[$itemno+1..$lastidx];
! 253: $#temp = $lastidx - 1;
! 254: $self->{KeyToLines} = Index(\@temp, $self->{Indexfield});
! 255: } else { # just need to truncate
! 256: $#temp = $lastidx-1; # the line array...
! 257: delete($index->{$key}); # and remove from index hash.
! 258: }
! 259: $self->{LineArray} = \@temp;
! 260:
! 261:
! 262: }
! 263: #
! 264: # Replace a line in the configuration file:
! 265: # The line is looked up by index.
! 266: # The line is replaced by the one passed in... note if the line
! 267: # is a comment, the index is just deleted!!
! 268: # The index for the line is replaced with the new value of the key field
! 269: # (it's possible the key field changed).
! 270: #
! 271: # Parameters:
! 272: # $self - Reference to the object's member data hash.
! 273: # $key - Lookup key.
! 274: # $line - New line.
! 275: # NOTE:
! 276: # If there is no line with the key $key, this reduces to an append.
! 277: #
! 278: sub ReplaceLine {
! 279: my $self = shift;
! 280: my $key = shift;
! 281: my $line = shift;
! 282:
! 283: my $hashref = $self->{KeyToLines};
! 284: if(!defined $hashref->{$key}) {
! 285: $self->Append($line);
! 286: } else {
! 287: my $l = $hashref->{$key};
! 288: my $lines = $self->{LineArray};
! 289: $lines->[$l] = $line; # Replace old line.
! 290: delete $hashref->{$key}; # get rid of the old index.
! 291: if(!Comment($line)) { # Index this line only if not comment!
! 292: my $newkey = Field($line, $self->{Indexfield});
! 293: $hashref->{$newkey} = $l;
! 294: }
! 295: }
! 296: }
! 297: 1;
! 298:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>