1 ###############################################################################
3 # Package: NaturalDocs::ReferenceString
5 ###############################################################################
7 # A package to manage <ReferenceString> handling throughout the program.
9 ###############################################################################
11 # This file is part of Natural Docs, which is Copyright © 2003-2010 Greg Valure
12 # Natural Docs is licensed under version 3 of the GNU Affero General Public License (AGPL)
13 # Refer to License.txt for the complete details
18 package NaturalDocs::ReferenceString;
20 use vars '@ISA', '@EXPORT';
22 @EXPORT = ( 'BINARYREF_NOTYPE', 'BINARYREF_NORESOLVINGFLAGS',
24 'REFERENCE_TEXT', 'REFERENCE_CH_CLASS', 'REFERENCE_CH_PARENT',
26 'RESOLVE_RELATIVE', 'RESOLVE_ABSOLUTE', 'RESOLVE_NOPLURAL', 'RESOLVE_NOUSING' );
28 use Encode qw(encode_utf8 decode_utf8);
32 # Constants: Binary Format Flags
34 # These flags can be combined to specify the format when using <ToBinaryFile()> and <FromBinaryFile()>. All are exported
37 # BINARYREF_NOTYPE - Do not include the <ReferenceType>.
38 # BINARYREF_NORESOLVEFLAGS - Do not include the <Resolving Flags>.
40 use constant BINARYREF_NOTYPE => 0x01;
41 use constant BINARYREF_NORESOLVINGFLAGS => 0x02;
45 # Constants: ReferenceType
47 # The type of a reference.
49 # REFERENCE_TEXT - The reference appears in the text of the documentation.
50 # REFERENCE_CH_CLASS - A class reference handled by <NaturalDocs::ClassHierarchy>.
51 # REFERENCE_CH_PARENT - A parent class reference handled by <NaturalDocs::ClassHierarchy>.
55 # - <ToBinaryFile()> and <FromBinaryFile()> require that these values fit into a UInt8, i.e. are <= 255.
57 use constant REFERENCE_TEXT => 1;
58 use constant REFERENCE_CH_CLASS => 2;
59 use constant REFERENCE_CH_PARENT => 3;
63 # Constants: Resolving Flags
65 # Used to influence the method of resolving references in <NaturalDocs::SymbolTable>.
67 # RESOLVE_RELATIVE - The reference text is truly relative, rather than Natural Docs' semi-relative.
68 # RESOLVE_ABSOLUTE - The reference text is always absolute. No local or relative references.
69 # RESOLVE_NOPLURAL - The reference text may not be interpreted as a plural, and thus match singular forms as well.
70 # RESOLVE_NOUSING - The reference text may not include "using" statements when being resolved.
72 # If neither <RESOLVE_RELATIVE> or <RESOLVE_ABSOLUTE> is specified, Natural Docs' semi-relative kicks in instead,
73 # which is where links are interpreted as local, then global, then relative. <RESOLVE_RELATIVE> states that links are
74 # local, then relative, then global.
78 # - <ToBinaryFile()> and <FromBinaryFile()> require that these values fit into a UInt8, i.e. are <= 255.
80 use constant RESOLVE_RELATIVE => 0x01;
81 use constant RESOLVE_ABSOLUTE => 0x02;
82 use constant RESOLVE_NOPLURAL => 0x04;
83 use constant RESOLVE_NOUSING => 0x08;
90 # Encodes the passed information as a <ReferenceString>. The format of the string should be treated as opaque. However, the
91 # characteristic you can rely on is that the same string will always be made from the same parameters, and thus it's suitable
92 # for comparison and use as hash keys.
96 # type - The <ReferenceType>.
97 # symbol - The <SymbolString> of the reference.
98 # language - The name of the language that defines the file this reference appears in.
99 # scope - The scope <SymbolString> the reference appears in, or undef if none.
100 # using - An arrayref of scope <SymbolStrings> that are also available for checking due to the equivalent a "using" statement,
102 # resolvingFlags - The <Resolving Flags> to use with this reference. They are ignored if the type is <REFERENCE_TEXT>.
106 # The encoded <ReferenceString>.
108 sub MakeFrom #(ReferenceType type, SymbolString symbol, string language, SymbolString scope, SymbolString[]* using, flags resolvingFlags)
110 my ($self, $type, $symbol, $language, $scope, $using, $resolvingFlags) = @_;
112 if ($type == ::REFERENCE_TEXT() || $resolvingFlags == 0)
113 { $resolvingFlags = undef; };
115 # The format is [type] 0x1E [resolving flags] 0x1E [symbol] 0x1E [scope] ( 0x1E [using] )*
116 # If there is no scope and/or using, the separator characters still remain.
118 # DEPENDENCY: SymbolString->FromText() removed all 0x1E characters.
119 # DEPENDENCY: SymbolString->FromText() doesn't use 0x1E characters in its encoding.
121 my $string = $type . "\x1E" . $symbol . "\x1E" . $language . "\x1E" . $resolvingFlags . "\x1E";
132 $string .= join("\x1E", @$using);
140 # Function: ToBinaryFile
142 # Writes a <ReferenceString> to the passed filehandle. Can also encode an undef.
146 # fileHandle - The filehandle to write to.
147 # referenceString - The <ReferenceString> to write, or undef.
148 # binaryFormatFlags - Any <Binary Format Flags> you want to use to influence encoding.
152 # > [SymbolString: Symbol or undef for an undef reference]
153 # > [UString16: language]
154 # > [SymbolString: Scope or undef for none]
156 # > [SymbolString: Using or undef for none]
157 # > [SymbolString: Using or undef for no more]
160 # > [UInt8: Type unless BINARYREF_NOTYPE is set]
161 # > [UInt8: Resolving Flags unless BINARYREF_NORESOLVINGFLAGS is set]
165 # - <ReferenceTypes> must fit into a UInt8. All values must be <= 255.
166 # - All <Resolving Flags> must fit into a UInt8. All values must be <= 255.
168 sub ToBinaryFile #(FileHandle fileHandle, ReferenceString referenceString, flags binaryFormatFlags)
170 my ($self, $fileHandle, $referenceString, $binaryFormatFlags) = @_;
172 my ($type, $symbol, $language, $scope, $using, $resolvingFlags) = $self->InformationOf($referenceString);
174 # [SymbolString: Symbol or undef for an undef reference]
176 NaturalDocs::SymbolString->ToBinaryFile($fileHandle, $symbol);
178 # [UString16: language]
180 # $language may be undefined because $referenceString may be undefined to end a list of them.
181 if (defined $language)
183 my $uLanguage = encode_utf8($language);
184 print $fileHandle pack('na*', length $uLanguage, $uLanguage);
187 { print $fileHandle pack('n', 0); }
189 # [SymbolString: scope or undef if none]
191 NaturalDocs::SymbolString->ToBinaryFile($fileHandle, $scope);
193 # [SymbolString: using or undef if none/no more] ...
197 foreach my $usingScope (@$using)
198 { NaturalDocs::SymbolString->ToBinaryFile($fileHandle, $usingScope); };
201 NaturalDocs::SymbolString->ToBinaryFile($fileHandle, undef);
203 # [UInt8: Type unless BINARYREF_NOTYPE is set]
205 if (!($binaryFormatFlags & BINARYREF_NOTYPE))
206 { print $fileHandle pack('C', $type); };
208 # [UInt8: Resolving Flags unless BINARYREF_NORESOLVINGFLAGS is set]
210 if (!($binaryFormatFlags & BINARYREF_NORESOLVINGFLAGS))
211 { print $fileHandle pack('C', $type); };
216 # Function: FromBinaryFile
218 # Reads a <ReferenceString> or undef from the passed filehandle.
222 # fileHandle - The filehandle to read from.
223 # binaryFormatFlags - Any <Binary Format Flags> you want to use to influence decoding.
224 # type - The <ReferenceType> to use if <BINARYREF_NOTYPE> is set.
225 # resolvingFlags - The <Resolving Flags> to use if <BINARYREF_NORESOLVINGFLAGS> is set.
229 # The <ReferenceString> or undef.
233 # See <ToBinaryFile()> for format and dependencies.
235 sub FromBinaryFile #(FileHandle fileHandle, flags binaryFormatFlags, ReferenceType type, flags resolvingFlags)
237 my ($self, $fileHandle, $binaryFormatFlags, $type, $resolvingFlags) = @_;
240 # [SymbolString: Symbol or undef for an undef reference]
242 my $symbol = NaturalDocs::SymbolString->FromBinaryFile($fileHandle);
244 if (!defined $symbol)
248 # [UString16: language]
250 read($fileHandle, $raw, 2);
251 my $languageLength = unpack('n', $raw);
254 read($fileHandle, $language, $languageLength);
255 $language = decode_utf8($language);
258 # [SymbolString: scope or undef if none]
260 my $scope = NaturalDocs::SymbolString->FromBinaryFile($fileHandle);
262 # [SymbolString: using or undef if none/no more] ...
267 while ($usingSymbol = NaturalDocs::SymbolString->FromBinaryFile($fileHandle))
268 { push @using, $usingSymbol; };
271 { $usingSymbol = \@using; }
273 { $usingSymbol = undef; };
275 # [UInt8: Type unless BINARYREF_NOTYPE is set]
277 if (!($binaryFormatFlags & BINARYREF_NOTYPE))
280 read($fileHandle, $raw, 1);
281 $type = unpack('C', $raw);
284 # [UInt8: Resolving Flags unless BINARYREF_NORESOLVINGFLAGS is set]
286 if (!($binaryFormatFlags & BINARYREF_NORESOLVINGFLAGS))
289 read($fileHandle, $raw, 1);
290 $resolvingFlags = unpack('C', $raw);
293 return $self->MakeFrom($type, $symbol, $language, $scope, $usingSymbol, $resolvingFlags);
298 # Function: InformationOf
300 # Returns the information encoded in a <ReferenceString>.
304 # referenceString - The <ReferenceString> to decode.
308 # The array ( type, symbol, language, scope, using, resolvingFlags ).
310 # type - The <ReferenceType>.
311 # symbol - The <SymbolString>.
312 # language - The name of the language that defined the file the reference was defined in.
313 # scope - The scope <SymbolString>, or undef if none.
314 # using - An arrayref of scope <SymbolStrings> that the reference also has access to via "using" statements, or undef if none.
315 # resolvingFlags - The <Resolving Flags> of the reference.
317 sub InformationOf #(ReferenceString referenceString)
319 my ($self, $referenceString) = @_;
321 my ($type, $symbolString, $language, $resolvingFlags, $scopeString, @usingStrings) = split(/\x1E/, $referenceString);
323 if (!length $resolvingFlags)
324 { $resolvingFlags = undef; };
326 return ( $type, $symbolString, $language, $scopeString, [ @usingStrings ], $resolvingFlags );
333 # Returns the <ReferenceType> encoded in the reference string. This is faster than <InformationOf()> if this is
334 # the only information you need.
336 sub TypeOf #(ReferenceString referenceString)
338 my ($self, $referenceString) = @_;
340 $referenceString =~ /^([^\x1E]+)/;