source: trunk/gsdl/perllib/doc.pm@ 1388

Last change on this file since 1388 was 1388, checked in by sjboddie, 24 years ago

fixed a bit of a bug (more of a typo really) in the recent changes made to
doc.pm::set_OID

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 22.2 KB
Line 
1###########################################################################
2#
3# doc.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26# base class to hold documents
27
28package doc;
29
30BEGIN {
31 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
32 unshift (@INC, "$ENV{'GSDLHOME'}/perllib/dynamic/lib/site_perl/5.005/i686-linux");
33}
34
35use unicode;
36use util;
37use ghtml;
38##use hashdoc;
39
40# the document type may be indexed_doc, nonindexed_doc, or
41# classification
42
43sub new {
44 my $class = shift (@_);
45 my ($source_filename, $doc_type) = @_;
46
47 my $self = bless {'associated_files'=>[],
48 'subsection_order'=>[],
49 'next_subsection'=>1,
50 'subsections'=>{},
51 'metadata'=>[],
52 'text'=>""}, $class;
53
54 $self->set_source_filename ($source_filename) if defined $source_filename;
55 $self->set_doc_type ($doc_type) if defined $doc_type;
56
57 return $self;
58}
59
60# clone the $self object
61sub duplicate {
62 my $self = shift (@_);
63
64 my $newobj = {};
65
66 foreach $k (keys %$self) {
67 $newobj->{$k} = &clone ($self->{$k});
68 }
69
70 bless $newobj, ref($self);
71 return $newobj;
72}
73
74sub clone {
75 my ($from) = @_;
76 my $type = ref ($from);
77
78 if ($type eq "HASH") {
79 my $to = {};
80 foreach $key (keys %$from) {
81 $to->{$key} = &clone ($from->{$key});
82 }
83 return $to;
84 } elsif ($type eq "ARRAY") {
85 my $to = [];
86 foreach $v (@$from) {
87 push (@$to, &clone ($v));
88 }
89 return $to;
90 } else {
91 return $from;
92 }
93}
94
95
96sub set_source_filename {
97 my $self = shift (@_);
98 my ($source_filename) = @_;
99
100 $self->set_metadata_element ($self->get_top_section(),
101 "gsdlsourcefilename",
102 $source_filename);
103}
104
105# returns the source_filename as it was provided
106sub get_source_filename {
107 my $self = shift (@_);
108
109 return $self->get_metadata_element ($self->get_top_section(), "gsdlsourcefilename");
110}
111
112sub set_doc_type {
113 my $self = shift (@_);
114 my ($doc_type) = @_;
115
116 $self->set_metadata_element ($self->get_top_section(),
117 "gsdldoctype",
118 $doc_type);
119}
120
121# returns the source_filename as it was provided
122# the default of "indexed_doc" is used if no document
123# type was provided
124sub get_doc_type {
125 my $self = shift (@_);
126
127 my $doc_type = $self->get_metadata_element ($self->get_top_section(), "gsdldoctype");
128 return $doc_type if (defined $doc_type);
129 return "indexed_doc";
130}
131
132sub _escape_text {
133 my ($text) = @_;
134
135 # special characters in the gml encoding
136 $text =~ s/&/&/g; # this has to be first...
137 $text =~ s/</&lt;/g;
138 $text =~ s/>/&gt;/g;
139 $text =~ s/\"/&quot;/g;
140
141 return $text;
142}
143
144
145sub buffer_section {
146 my $self = shift (@_);
147 my ($section, $suppress_subject_info) = @_;
148
149 $suppress_subject_info = 0 unless defined $suppress_subject_info;
150 my ($all_text,$data, $subsection);
151
152 my $section_ptr = $self->_lookup_section ($section);
153 my ($section_num) = $section =~ /(\d+)$/;
154
155 return "" unless defined $section_ptr;
156
157 # output the section header (including the section number
158 # and metadata)
159
160 $all_text = "<gsdlsection";
161 $all_text .= " gsdlnum=\"$section_num\"" if defined $section_num;
162 foreach $data (@{$section_ptr->{'metadata'}}) {
163 $all_text .= " $data->[0]=\"" . &_escape_text($data->[1]) . "\""
164 unless $suppress_subject_info && $data->[0] eq "Subject";
165 }
166 $all_text .= ">";
167
168 # output the text
169 $all_text .= &_escape_text($section_ptr->{'text'});
170
171 # output all the subsections
172 foreach $subsection (@{$section_ptr->{'subsection_order'}}) {
173 $all_text .= $self->buffer_section("$section.$subsection", $suppress_subject_info);
174 }
175
176 # output the closing tag
177 $all_text .= "</gsdlsection>\n";
178
179 return $all_text;
180}
181
182sub output_section {
183 my $self = shift (@_);
184 my ($handle, $section, $suppress_subject_info) = @_;
185
186 my $all_text = $self->buffer_section($section, $suppress_subject_info);
187 print $handle $all_text;
188}
189
190# look up the reference to the a particular section
191sub _lookup_section {
192 my $self = shift (@_);
193 my ($section) = @_;
194
195 my ($num);
196 my $sectionref = $self;
197
198 while (defined $section && $section ne "") {
199 ($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
200 $num =~ s/^0+(\d)/$1/; # remove leading 0s
201 $section = "" unless defined $section;
202
203 if (defined $num && defined $sectionref->{'subsections'}->{$num}) {
204 $sectionref = $sectionref->{'subsections'}->{$num};
205 } else {
206 return undef;
207 }
208 }
209
210 return $sectionref;
211}
212
213sub _calc_OID {
214 my $self = shift (@_);
215 my ($filename) = @_;
216
217 my $osexe = &util::get_os_exe();
218
219 my $hashfile_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",
220 $ENV{'GSDLOS'},"hashfile$osexe");
221 my $result = "NULL";
222
223 if (-e "$hashfile_exe") {
224 $result = `$hashfile_exe \"$filename\"`;
225 ($result) = $result =~ /:\s*([0-9a-f]+)/i;
226
227 } else {
228 print STDERR "doc::_calc_OID $hashfile_exe could not be found\n";
229 }
230
231 return "HASH$result";
232}
233
234# methods dealing with OID, not groups of them.
235
236# if $OID is not provided one is calculated from hashing the
237# current contents of the document
238# An OID are actually stored as metadata of the document
239sub set_OID {
240 my $self = shift (@_);
241 my ($OID) = @_;
242
243 # if an OID wasn't provided then feed this document to
244 # hashfile.exe
245 if (!defined $OID) {
246 $OID = "NULL";
247
248 my $filename = $self->get_source_filename();
249 if (defined($filename) && -e $filename) {
250
251 $OID = $self->_calc_OID ($filename);
252
253 } else {
254
255 print STDERR "doc::set_OID source filename undefined/non-existant (continuing)\n";
256
257 $filename = &util::get_tmp_filename();
258 if (!open (OUTFILE, ">$filename")) {
259 print STDERR "doc::set_OID could not write to $filename\n";
260 } else {
261 $self->output_section('OUTFILE', $self->get_top_section(), 1);
262 close (OUTFILE);
263 }
264
265 $OID = $self->_calc_OID ($filename);
266 &util::rm ($filename);
267 }
268 }
269
270 $self->set_metadata_element ($self->get_top_section(), "Identifier", $OID);
271}
272
273# this uses hashdoc (embedded c thingy) which is faster but still
274# needs a little work to be suffiently stable
275sub ___set_OID {
276 my $self = shift (@_);
277 my ($OID) = @_;
278
279 # if an OID wasn't provided then calculate hash value based on document
280 if (!defined $OID)
281 {
282 my $hash_text = $self->buffer_section($self->get_top_section(), 1);
283 my $hash_len = length($hash_text);
284
285 $OID = &hashdoc::buffer($hash_text,$hash_len);
286 }
287
288 $self->set_metadata_element ($self->get_top_section(), "Identifier", $OID);
289}
290
291# returns the OID for this document
292sub get_OID {
293 my $self = shift (@_);
294 my $OID = $self->get_metadata_element ($self->get_top_section(), "Identifier");
295 return $OID if (defined $OID);
296 return "NULL";
297}
298
299sub delete_OID {
300 my $self = shift (@_);
301
302 $self->set_metadata_element ($self->get_top_section(), "Identifier", "NULL");
303}
304
305
306# methods for manipulating section names
307
308# returns the name of the top-most section (the top
309# level of the document
310sub get_top_section {
311 my $self = shift (@_);
312
313 return "";
314}
315
316# returns a section
317sub get_parent_section {
318 my $self = shift (@_);
319 my ($section) = @_;
320
321 $section =~ s/(^|\.)\d+$//;
322
323 return $section;
324}
325
326# returns the first child section (or the end child
327# if there isn't any)
328sub get_begin_child {
329 my $self = shift (@_);
330 my ($section) = @_;
331
332 my $section_ptr = $self->_lookup_section($section);
333 return "" unless defined $section_ptr;
334
335 if (defined $section_ptr->{'subsection_order'}->[0]) {
336 return "$section.$section_ptr->{'subsection_order'}->[0]";
337 }
338
339 return $self->get_end_child ($section);
340}
341
342# returns the next child of a parent section
343sub get_next_child {
344 my $self = shift (@_);
345 my ($section) = @_;
346
347 my $parent_section = $self->get_parent_section($section);
348 my $parent_section_ptr = $self->_lookup_section($parent_section);
349 return undef unless defined $parent_section_ptr;
350
351 my ($section_num) = $section =~ /(\d+)$/;
352 return undef unless defined $section_num;
353
354 my $i = 0;
355 my $section_order = $parent_section_ptr->{'subsection_order'};
356 while ($i < scalar(@$section_order)) {
357 last if $section_order->[$i] eq $section_num;
358 $i++;
359 }
360
361 $i++; # the next child
362 if ($i < scalar(@$section_order)) {
363 return $section_order->[$i] if $parent_section eq "";
364 return "$parent_section.$section_order->[$i]";
365 }
366
367 # no more sections in this level
368 return undef;
369}
370
371# returns a reference to a list of children
372sub get_children {
373 my $self = shift (@_);
374 my ($section) = @_;
375
376 my $section_ptr = $self->_lookup_section($section);
377 return [] unless defined $section_ptr;
378
379 my @children = @{$section_ptr->{'subsection_order'}};
380
381 map {$_ = "$section.$_"; $_ =~ s/^\.+//;} @children;
382 return \@children;
383}
384
385# returns the child section one past the last one (which
386# is coded as "0")
387sub get_end_child {
388 my $self = shift (@_);
389 my ($section) = @_;
390
391 return $section . ".0" unless $section eq "";
392 return "0";
393}
394
395# returns the next section in book order
396sub get_next_section {
397 my $self = shift (@_);
398 my ($section) = @_;
399
400 return undef unless defined $section;
401
402 my $section_ptr = $self->_lookup_section($section);
403 return undef unless defined $section_ptr;
404
405 # first try to find first child
406 if (defined $section_ptr->{'subsection_order'}->[0]) {
407 return $section_ptr->{'subsection_order'}->[0] if ($section eq "");
408 return "$section.$section_ptr->{'subsection_order'}->[0]";
409 }
410
411 do {
412 # try to find sibling
413 my $next_child = $self->get_next_child ($section);
414 return $next_child if (defined $next_child);
415
416 # move up one level
417 $section = $self->get_parent_section ($section);
418 } while $section =~ /\d/;
419
420 return undef;
421}
422
423sub is_leaf_section {
424 my $self = shift (@_);
425 my ($section) = @_;
426
427 my $section_ptr = $self->_lookup_section($section);
428 return 1 unless defined $section_ptr;
429
430 return (scalar (@{$section_ptr->{'subsection_order'}}) == 0);
431}
432
433# methods for dealing with sections
434
435# returns the name of the inserted section
436sub insert_section {
437 my $self = shift (@_);
438 my ($before_section) = @_;
439
440 # get the child to insert before and its parent section
441 my $parent_section = "";
442 my $before_child = "0";
443 my @before_section = split (/\./, $before_section);
444 if (scalar(@before_section) > 0) {
445 $before_child = pop (@before_section);
446 $parent_section = join (".", @before_section);
447 }
448
449 my $parent_section_ptr = $self->_lookup_section($parent_section);
450 if (!defined $parent_section_ptr) {
451 print STDERR "doc::insert_section couldn't find parent section " .
452 "$parent_section\n";
453 return;
454 }
455
456 # get the next section number
457 my $section_num = $parent_section_ptr->{'next_subsection'}++;
458
459 my $i = 0;
460 while ($i < scalar(@{$parent_section_ptr->{'subsection_order'}}) &&
461 $parent_section_ptr->{'subsection_order'}->[$i] ne $before_child) {
462 $i++;
463 }
464
465 # insert the section number into the order list
466 splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 0, $section_num);
467
468 # add this section to the parent section
469 my $section_ptr = {'subsection_order'=>[],
470 'next_subsection'=>1,
471 'subsections'=>{},
472 'metadata'=>[],
473 'text'=>""};
474 $parent_section_ptr->{'subsections'}->{$section_num} = $section_ptr;
475
476 # work out the full section number
477 my $section = $parent_section;
478 $section .= "." unless $section eq "";
479 $section .= $section_num;
480
481 return $section;
482}
483
484# creates a pre-named section
485sub create_named_section {
486 my $self = shift (@_);
487 my ($mastersection) = @_;
488
489 my ($num);
490 my $section = $mastersection;
491 my $sectionref = $self;
492
493#### print STDERR "*** mastersection = $mastersection\n";
494
495 while ($section ne "") {
496 ($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
497 $num =~ s/^0+(\d)/$1/; # remove leading 0s
498 $section = "" unless defined $section;
499
500 if (defined $num) {
501 if (!defined $sectionref->{'subsections'}->{$num}) {
502 push (@{$sectionref->{'subsection_order'}}, $num);
503 $sectionref->{'subsections'}->{$num} = {'subsection_order'=>[],
504 'next_subsection'=>1,
505 'subsections'=>{},
506 'metadata'=>[],
507 'text'=>""};
508 if ($num >= $sectionref->{'next_subsection'}) {
509 $sectionref->{'next_subsection'} = $num + 1;
510 }
511 }
512 $sectionref = $sectionref->{'subsections'}->{$num};
513
514 } else {
515 print STDERR "doc::create_named_section couldn't create section ";
516 print STDERR "$mastersection\n";
517 last;
518 }
519 }
520}
521
522# returns a reference to a list of subsections
523sub list_subsections {
524 my $self = shift (@_);
525 my ($section) = @_;
526
527 my $section_ptr = $self->_lookup_section ($section);
528 if (!defined $section_ptr) {
529 print STDERR "doc::list_subsections couldn't find section $section\n";
530 return [];
531 }
532
533 return [@{$section_ptr->{'subsection_order'}}];
534}
535
536sub delete_section {
537 my $self = shift (@_);
538 my ($section) = @_;
539
540# my $section_ptr = {'subsection_order'=>[],
541# 'next_subsection'=>1,
542# 'subsections'=>{},
543# 'metadata'=>[],
544# 'text'=>""};
545
546 # if this is the top section reset everything
547 if ($section eq "") {
548 $self->{'subsection_order'} = [];
549 $self->{'subsections'} = {};
550 $self->{'metadata'} = [];
551 $self->{'text'} = "";
552 return;
553 }
554
555 # find the parent of the section to delete
556 my $parent_section = "";
557 my $child = "0";
558 my @section = split (/\./, $section);
559 if (scalar(@section) > 0) {
560 $child = pop (@section);
561 $parent_section = join (".", @section);
562 }
563
564 my $parent_section_ptr = $self->_lookup_section($parent_section);
565 if (!defined $parent_section_ptr) {
566 print STDERR "doc::delete_section couldn't find parent section " .
567 "$parent_section\n";
568 return;
569 }
570
571 # remove this section from the subsection_order list
572 my $i = 0;
573 while ($i < scalar (@{$parent_section_ptr->{'subsection_order'}})) {
574 if ($parent_section_ptr->{'subsection_order'}->[$i] eq $child) {
575 splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 1);
576 last;
577 }
578 $i++;
579 }
580
581 # remove this section from the subsection hash
582 if (defined ($parent_section_ptr->{'subsections'}->{$child})) {
583 undef $parent_section_ptr->{'subsections'}->{$child};
584 }
585}
586
587#--
588# methods for dealing with metadata
589
590# set_metadata_element and get_metadata_element are for metadata
591# which should only have one value. add_meta_data and get_metadata
592# are for metadata which can have more than one value.
593
594# returns the first metadata value which matches field
595sub get_metadata_element {
596 my $self = shift (@_);
597 my ($section, $field) = @_;
598 my ($data);
599
600 my $section_ptr = $self->_lookup_section($section);
601 if (!defined $section_ptr) {
602 print STDERR "doc::get_metadata_element couldn't find section " .
603 "$section\n";
604 return;
605 }
606
607 foreach $data (@{$section_ptr->{'metadata'}}) {
608 return $data->[1] if (scalar(@$data) >= 2 && $data->[0] eq $field);
609 }
610
611 return undef; # was not found
612}
613
614
615# returns a list of the form [value1, value2, ...]
616sub get_metadata {
617 my $self = shift (@_);
618 my ($section, $field) = @_;
619 my ($data);
620
621 my $section_ptr = $self->_lookup_section($section);
622 if (!defined $section_ptr) {
623 print STDERR "doc::get_metadata couldn't find section " .
624 "$section\n";
625 return;
626 }
627
628 my @metadata = ();
629 foreach $data (@{$section_ptr->{'metadata'}}) {
630 push (@metadata, $data->[1]) if ($data->[0] eq $field);
631 }
632
633 return \@metadata;
634}
635
636# returns a list of the form [[field,value],[field,value],...]
637sub get_all_metadata {
638 my $self = shift (@_);
639 my ($section) = @_;
640
641 my $section_ptr = $self->_lookup_section($section);
642 if (!defined $section_ptr) {
643 print STDERR "doc::get_all_metadata couldn't find section " .
644 "$section\n";
645 return;
646 }
647
648 return $section_ptr->{'metadata'};
649}
650
651# $value is optional
652sub delete_metadata {
653 my $self = shift (@_);
654 my ($section, $field, $value) = @_;
655
656 my $section_ptr = $self->_lookup_section($section);
657 if (!defined $section_ptr) {
658 print STDERR "doc::delete_metadata couldn't find section " .
659 "$section\n";
660 return;
661 }
662
663 my $i = 0;
664 while ($i < scalar (@{$section_ptr->{'metadata'}})) {
665 if (($section_ptr->{'metadata'}->[$i]->[0] eq $field) &&
666 (!defined $value || $section_ptr->{'metadata'}->[$i]->[1] eq $value)) {
667 splice (@{$section_ptr->{'metadata'}}, $i, 1);
668 } else {
669 $i++;
670 }
671 }
672}
673
674sub delete_all_metadata {
675 my $self = shift (@_);
676 my ($section) = @_;
677
678 my $section_ptr = $self->_lookup_section($section);
679 if (!defined $section_ptr) {
680 print STDERR "doc::delete_all_metadata couldn't find section " .
681 "$section\n";
682 return;
683 }
684
685 $section_ptr->{'metadata'} = [];
686}
687
688sub set_metadata_element {
689 my $self = shift (@_);
690 my ($section, $field, $value) = @_;
691
692 $self->set_utf8_metadata_element ($section, $field,
693 &unicode::ascii2utf8($value));
694}
695
696# set_utf8_metadata_element assumes the text has already been
697# converted to the UTF-8 encoding.
698sub set_utf8_metadata_element {
699 my $self = shift (@_);
700 my ($section, $field, $value) = @_;
701
702 $self->delete_metadata ($section, $field);
703 $self->add_utf8_metadata ($section, $field, $value);
704}
705
706
707# add_metadata assumes the text is in (extended) ascii form. For
708# text which hash been already converted to the UTF-8 format use
709# add_utf8_metadata.
710sub add_metadata {
711 my $self = shift (@_);
712 my ($section, $field, $value) = @_;
713
714 $self->add_utf8_metadata ($section, $field,
715 &unicode::ascii2utf8($value));
716}
717
718# add_utf8_metadata assumes the text has already been converted
719# to the UTF-8 encoding.
720sub add_utf8_metadata {
721 my $self = shift (@_);
722 my ($section, $field, $value) = @_;
723
724 my $section_ptr = $self->_lookup_section($section);
725 if (!defined $section_ptr) {
726 print STDERR "doc::add_utf8_metadata couldn't find section " .
727 "$section\n";
728 return;
729 }
730
731 push (@{$section_ptr->{'metadata'}}, [$field, $value]);
732}
733
734
735# methods for dealing with text
736
737# returns the text for a section
738sub get_text {
739 my $self = shift (@_);
740 my ($section) = @_;
741
742 my $section_ptr = $self->_lookup_section($section);
743 if (!defined $section_ptr) {
744 print STDERR "doc::get_text couldn't find section " .
745 "$section\n";
746 return "";
747 }
748
749 return $section_ptr->{'text'};
750}
751
752# returns the (utf-8 encoded) length of the text for a section
753sub get_text_length {
754 my $self = shift (@_);
755 my ($section) = @_;
756
757 my $section_ptr = $self->_lookup_section($section);
758 if (!defined $section_ptr) {
759 print STDERR "doc::get_text_length couldn't find section " .
760 "$section\n";
761 return 0;
762 }
763
764 return length ($section_ptr->{'text'});
765}
766
767sub delete_text {
768 my $self = shift (@_);
769 my ($section) = @_;
770
771 my $section_ptr = $self->_lookup_section($section);
772 if (!defined $section_ptr) {
773 print STDERR "doc::delete_text couldn't find section " .
774 "$section\n";
775 return;
776 }
777
778 $section_ptr->{'text'} = "";
779}
780
781# add_text assumes the text is in (extended) ascii form. For
782# text which has been already converted to the UTF-8 format
783# use add_utf8_text.
784sub add_text {
785 my $self = shift (@_);
786 my ($section, $text) = @_;
787
788 # convert the text to UTF-8 encoded unicode characters
789 # and add the text
790 $self->add_utf8_text($section, &unicode::ascii2utf8($text));
791}
792
793
794# add_utf8_text assumes the text to be added has already
795# been converted to the UTF-8 encoding. For ascii text use
796# add_text
797sub add_utf8_text {
798 my $self = shift (@_);
799 my ($section, $text) = @_;
800
801 my $section_ptr = $self->_lookup_section($section);
802 if (!defined $section_ptr) {
803 print STDERR "doc::add_utf8_text couldn't find section " .
804 "$section\n";
805 return;
806 }
807
808 $section_ptr->{'text'} .= $text;
809}
810
811
812# methods for dealing with associated files
813
814# a file is associated with a document, NOT a section.
815# if section is defined it is noted in the data structure
816# only so that files associated from a particular section
817# may be removed later (using delete_section_assoc_files)
818sub associate_file {
819 my $self = shift (@_);
820 my ($real_filename, $assoc_filename, $mime_type, $section) = @_;
821 $mime_type = &ghtml::guess_mime_type ($real_filename) unless defined $mime_type;
822
823 # remove all associated files with the same name
824 $self->delete_assoc_file ($assoc_filename);
825
826 push (@{$self->{'associated_files'}},
827 [$real_filename, $assoc_filename, $mime_type, $section]);
828}
829
830# returns a list of associated files in the form
831# [[real_filename, assoc_filename, mimetype], ...]
832sub get_assoc_files {
833 my $self = shift (@_);
834
835 return $self->{'associated_files'};
836}
837
838sub delete_section_assoc_files {
839 my $self = shift (@_);
840 my ($section) = @_;
841
842 my $i=0;
843 while ($i < scalar (@{$self->{'associated_files'}})) {
844 if (defined $self->{'associated_files'}->[$i]->[3] &&
845 $self->{'associated_files'}->[$i]->[3] eq $section) {
846 splice (@{$self->{'associated_files'}}, $i, 1);
847 } else {
848 $i++;
849 }
850 }
851}
852
853sub delete_assoc_file {
854 my $self = shift (@_);
855 my ($assoc_filename) = @_;
856
857 my $i=0;
858 while ($i < scalar (@{$self->{'associated_files'}})) {
859 if ($self->{'associated_files'}->[$i]->[1] eq $assoc_filename) {
860 splice (@{$self->{'associated_files'}}, $i, 1);
861 } else {
862 $i++;
863 }
864 }
865}
866
867sub reset_nextsection_ptr {
868 my $self = shift (@_);
869 my ($section) = @_;
870
871 my $section_ptr = $self->_lookup_section($section);
872 $section_ptr->{'next_subsection'} = 1;
873}
874
8751;
Note: See TracBrowser for help on using the repository browser.