1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Default implementation of the Attributes interface.
12 module sax
::attributes_impl
14 import sax
::attributes
16 # Default implementation of the Attributes interface.
18 # This class provides a default implementation of the SAX2
19 # `Attributes` interface, with the addition of manipulators so that the list
20 # can be modified or reused.
22 # There are two typical uses of this class:
24 # * to take a persistent snapshot of an Attributes object in a `start_element`
26 # * to construct or modify an Attributes object in a SAX2 driver or filter.
28 # Note: The original source code and documentation of this class comes, in part,
29 # from [SAX 2.0](http://www.saxproject.org).
33 private var data
= new Array[String]
36 redef fun uri
(index
) do
37 if index
>= 0 and index
< length
then
38 return data
[index
* 5]
44 redef fun local_name
(index
) do
45 if index
>= 0 and index
< length
then
46 return data
[index
* 5 + 1]
52 redef fun qname
(index
) do
53 if index
>= 0 and index
< length
then
54 return data
[index
* 5 + 2]
60 # Look up an attribute's type by index.
62 # The attribute type is one of the strings `CDATA`, `ID`,
63 # `IDREF`, `IDREFS`, `NMTOKEN`, `NMTOKENS`, `ENTITY`, `ENTITIES`,
64 # or `NOTATION` (always in upper case).
66 # If the parser has not read a declaration for the attribute,
67 # or if the parser does not report attribute types, then it must
68 # return the value `CDATA` as stated in the XML 1.0 Recommentation
69 # (clause 3.3.3, "Attribute-Value Normalization").
71 # For an enumerated attribute that is not a notation, the
72 # parser will report the type as `NMTOKEN`.
76 # * `index: Int`: attribute index.
77 # * `index: String`: XML 1.0 qualified (prefixed) name.
78 # In many cases, it will be more efficient to look up the name once and
79 # query by `Int` index rather than quering by name repeatedly.
83 # The attribute's type as a string, or `null` if the specified
84 # attribute is not in the list or if qualified names
88 redef fun type_of
(index
) do
90 if index
>= 0 and index
< length
then
91 return data
[index
* 5 + 3]
93 else if index
isa String and "" != index
then
96 while i
< data
.length
do
97 if data
[i
+ 2] == index
then
106 # Look up an attribute's value by index.
108 # If the attribute value is a list of tokens (`IDREFS`,
109 # `ENTITIES`, or `NMTOKENS`), the tokens will be concatenated
110 # into a single string with each token separated by a
115 # * `index: Int`: attribute index.
116 # * `index: String`: XML 1.0 qualified (prefixed) name.
117 # In many cases, it will be more efficient to look up the name once and
118 # query by `Int` index rather than quering by name repeatedly.
122 # The attribute's value as a string, or `null` if the specified
123 # attribute is not in the list or if qualified names
127 redef fun value_of
(index
) do
128 if index
isa Int then
129 if index
>= 0 and index
< length
then
130 return data
[index
* 5 + 4]
132 else if index
isa String and "" != index
then
135 while i
< data
.length
do
136 if data
[i
+ 2] == index
then
145 # Look up the index of an attribute by Namespace name.
147 # In many cases, it will be more efficient to look up the name once and
148 # query by `Int` index rather than quering by name repeatedly.
152 # * `uri`: Namespace URI, or the empty string if
153 # the name has no Namespace URI.
154 # * `local_name`: attribute's local name.
158 # The index of the attribute, or -1 if it does not
159 # appear in the list.
160 redef fun index_ns
(uri
, local_name
) do
163 if "" != local_name
then
164 while i
< data
.length
do
165 if data
[i
] == uri
and data
[i
+ 1] == local_name
then
174 # Look up the index of an attribute by XML 1.0 qualified name.
176 # In many cases, it will be more efficient to look up the name once and
177 # query by `Int` index rather than quering by name repeatedly.
181 # * `qname`: XML 1.0 qualified (prefixed) name.
185 # The index of the attribute, or -1 if it does not
186 # appear in the list.
187 redef fun index_of
(qname
) do
191 while i
< data
.length
do
192 if data
[i
+ 2] == qname
then
201 # Look up an attribute's type by Namespace name.
203 # In many cases, it will be more efficient to look up the name once and
204 # query by `Int` index rather than quering by name repeatedly.
206 # See `type_of` for a description
207 # of the possible types.
211 # * `uri`: Namespace URI, or the empty string if
212 # the name has no Namespace URI.
214 # * `local_name`: attribute's local name.
218 # The attribute type as a string, or `null` if the
219 # attribute is not in the list or if Namespace
220 # processing is not being performed.
221 redef fun type_ns
(uri
, local_name
) do
224 if "" != local_name
then
225 while i
< data
.length
do
226 if data
[i
] == uri
and data
[i
+ 1] == local_name
then
235 # Look up an attribute's value by Namespace name.
237 # In many cases, it will be more efficient to look up the name once and
238 # query by `Int` index rather than quering by name repeatedly.
240 # See `value_of` for a description
241 # of the possible values.
245 # * `uri`: Namespace URI, or the empty string if
246 # the name has no Namespace URI.
248 # * `local_name`: attribute's local name.
252 # The attribute value as a string, or `null` if the
253 # attribute is not in the list or if Namespace
254 # processing is not being performed.
255 redef fun value_ns
(uri
, local_name
) do
258 if "" != local_name
then
259 while i
< data
.length
do
260 if data
[i
] == uri
and data
[i
+ 1] == local_name
then
269 # Clear the attribute list for reuse.
275 # Copy an entire Attributes object.
277 # It may be more efficient to reuse an existing object
278 # rather than constantly allocating new ones.
282 # * `atts`: attributes to copy.
283 fun attributes
=(atts
: Attributes) do
288 data
.enlarge
(length
* 5)
290 data
.push
(atts
.uri
(i
).as(not null))
291 data
.push
(atts
.local_name
(i
).as(not null))
292 data
.push
(atts
.qname
(i
).as(not null))
293 data
.push
(atts
.type_of
(i
).as(not null))
294 data
.push
(atts
.value_of
(i
).as(not null))
299 # Add an attribute to the end of the list.
301 # For the sake of speed, this method does no checking
302 # to see if the attribute is already in the list: that is
303 # the responsibility of the application.
307 # * `uri`: Namespace URI, or the empty string if
308 # none is available or Namespace processing is not being performed.
309 # * `local_name`: local name, or the empty string if
310 # Namespace processing is not being performed.
311 # * `qname`: qualified (prefixed) name, or the empty string
312 # if qualified names are not available.
313 # * `attribute_type`: attribute type as a string.
314 # * `value`: attribute value.
315 fun add
(uri
: String, local_name
: String, qname
: String,
316 attribute_type
: String, value
: String) do
317 ensure_capacity
(length
+ 1)
319 data
.push
(local_name
)
321 data
.push
(attribute_type
)
326 # Set an attribute in the list.
328 # For the sake of speed, this method does no checking
329 # for name conflicts or well-formedness: such checks are the
330 # responsibility of the application.
334 # * `index`: index of the attribute (zero-based).
335 # * `uri`: Namespace URI, or the empty string if
336 # none is available or Namespace processing is not being performed.
337 # * `local_name`: local name, or the empty string if
338 # Namespace processing is not being performed.
339 # * `qname`: qualified (prefixed) name, or the empty string
340 # if qualified names are not available.
341 # * `attribute_type`: attribute type as a string.
342 # * `value`: attribute value.
343 fun set
(index
: Int, uri
: String, local_name
: String, qname
: String,
344 attribute_type
: String, value
: String) do
345 assert index_in_bounds
: index
>= 0 and index
< length
346 data
[index
* 5] = uri
347 data
[index
* 5 + 1] = local_name
348 data
[index
* 5 + 2] = qname
349 data
[index
* 5 + 3] = attribute_type
350 data
[index
* 5 + 4] = value
353 # Remove an attribute from the list.
357 # * `index`: index of the attribute (zero-based).
358 fun remove_at
(index
: Int) do
359 assert index_in_bounds
: index
>= 0 and index
< length
362 data
.remove_at
(index
)
367 # Set the Namespace URI of a specific attribute.
371 # * `index`: index of the attribute (zero-based).
372 # * `uri`: attribute's Namespace URI, or the empty string for none.
373 fun uri
=(index
: Int, uri
: String) do
374 assert index_in_bounds
: index
>= 0 and index
< length
375 data
[index
* 5] = uri
378 # Set the local name of a specific attribute.
382 # * `index`: index of the attribute (zero-based).
383 # * `local_name`: attribute's local name, or the empty string for none.
384 fun local_name
=(index
: Int, local_name
: String) do
385 assert index_in_bounds
: index
>= 0 and index
< length
386 data
[index
* 5 + 1] = local_name
389 # Set the qualified name of a specific attribute.
393 # * `index`: index of the attribute (zero-based).
394 # * `qname`: attribute's qualified name, or the empty string for none.
395 fun qname
=(index
: Int, qname
: String) do
396 assert index_in_bounds
: index
>= 0 and index
< length
397 data
[index
* 5 + 2] = qname
400 # Set the type of a specific attribute.
404 # * `index`: index of the attribute (zero-based).
405 # * `attribute_type`: attribute's type.
406 fun type_of
=(index
: Int, attribute_type
: String) do
407 assert index_in_bounds
: index
>= 0 and index
< length
408 data
[index
* 5 + 3] = attribute_type
411 # Set the value of a specific attribute.
415 # * `index`: index of the attribute (zero-based).
416 # * `value`: attribute's value.
417 fun value_of
=(index
: Int, value
: String) do
418 assert index_in_bounds
: index
>= 0 and index
< length
419 data
[index
* 5 + 4] = value
422 # Ensure the internal array's capacity.
426 # * `n`: minimum number of attributes that the array must be able to hold.
427 private fun ensure_capacity
(n
: Int) do