mirror of
https://github.com/AdaCore/xmlada.git
synced 2026-02-12 12:30:28 -08:00
... to allow to reuse node inside the same document and to avoid dangling pointers. Raise exception when node is not found as required by DOM specification. Change-Id: I46eabf3938afba56a1f5061db6f1b2ded186a6e6
386 lines
14 KiB
Ada
386 lines
14 KiB
Ada
------------------------------------------------------------------------------
|
|
-- XML/Ada - An XML suite for Ada95 --
|
|
-- --
|
|
-- Copyright (C) 2001-2021, AdaCore --
|
|
-- --
|
|
-- This library is free software; you can redistribute it and/or modify it --
|
|
-- under terms of the GNU General Public License as published by the Free --
|
|
-- Software Foundation; either version 3, or (at your option) any later --
|
|
-- version. This library is distributed in the hope that it will be useful, --
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
|
|
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
|
|
-- --
|
|
-- As a special exception under Section 7 of GPL version 3, you are granted --
|
|
-- additional permissions described in the GCC Runtime Library Exception, --
|
|
-- version 3.1, as published by the Free Software Foundation. --
|
|
-- --
|
|
-- You should have received a copy of the GNU General Public License and --
|
|
-- a copy of the GCC Runtime Library Exception along with this program; --
|
|
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
|
|
-- <http://www.gnu.org/licenses/>. --
|
|
-- --
|
|
------------------------------------------------------------------------------
|
|
|
|
-- This package is the root hierarchy for the Core part of the DOM
|
|
-- interface.
|
|
-- It is in fact made of several subpackages, since DOM provides
|
|
-- two views of the tree: Object-oriented throught the Element, Document,...
|
|
-- types; and direct access through the Node interface.
|
|
|
|
pragma Ada_05;
|
|
|
|
with Unicode.CES;
|
|
with Ada.Unchecked_Deallocation;
|
|
with Sax.HTable;
|
|
with Sax.Symbols;
|
|
with Sax.Utils;
|
|
|
|
package DOM.Core is
|
|
|
|
Default_Node_List_Growth_Factor : constant Float := 1.0;
|
|
-- Set to 1.0 the buffer is doubled in size (growth factor is 100%).
|
|
-- If set to 0.0 only a single empty items is added.
|
|
-- The higher this factor, the less memory allocations will be required
|
|
-- (and thus the faster your program will run).
|
|
-- Setting this to 0.0 will require more allocations, but will save memory,
|
|
-- since no empty node will remain in the final tree.
|
|
|
|
subtype DOM_String is Unicode.CES.Byte_Sequence;
|
|
-- A simple redefinition of the strings, to be compatible with the
|
|
-- standard DOM interface
|
|
-- See the package Encodings for the exact encoding used for DOM_Strings
|
|
|
|
subtype DOM_String_Access is Unicode.CES.Byte_Sequence_Access;
|
|
|
|
-----------
|
|
-- Nodes --
|
|
-----------
|
|
-- This is the base type for all DOM.Core types. It is declared in this
|
|
-- package for visibility reasons, so that all DOM.Core.* packages have
|
|
-- access to the components.
|
|
|
|
type Node_Types is
|
|
(Element_Node,
|
|
Attribute_Node,
|
|
Cdata_Section_Node,
|
|
Entity_Reference_Node,
|
|
Entity_Node,
|
|
Processing_Instruction_Node,
|
|
Text_Node,
|
|
Comment_Node,
|
|
Document_Node,
|
|
Document_Type_Node,
|
|
Document_Fragment_Node,
|
|
Notation_Node);
|
|
|
|
subtype Character_Data_Types is Node_Types range Text_Node .. Comment_Node;
|
|
|
|
type Node_Record (Node_Type : Node_Types) is private;
|
|
type Node is access Node_Record;
|
|
|
|
subtype Character_Data is Node;
|
|
subtype Element is Node (Element_Node);
|
|
subtype Attr is Node (Attribute_Node);
|
|
subtype Cdata_Section is Character_Data (Cdata_Section_Node);
|
|
subtype Entity_Reference is Node (Entity_Reference_Node);
|
|
subtype Entity is Node (Entity_Node);
|
|
subtype Processing_Instruction is Node (Processing_Instruction_Node);
|
|
subtype Text is Character_Data (Text_Node);
|
|
subtype Comment is Character_Data (Comment_Node);
|
|
subtype Document is Node (Document_Node);
|
|
subtype Document_Type is Node (Document_Type_Node);
|
|
subtype Document_Fragment is Node (Document_Fragment_Node);
|
|
subtype Notation is Node (Notation_Node);
|
|
|
|
type Node_List is private;
|
|
-- A simple ordered list of nodes (see DOM.Core.Nodes for subprograms)
|
|
|
|
type Named_Node_Map is private;
|
|
-- A collection of nodes accessible by their names.
|
|
-- This is unordered.
|
|
|
|
procedure Free (List : in out Node_List);
|
|
-- Free the memory occupied by the list. The items contained in the list
|
|
-- are not freed, since they still exist in the XML tree.
|
|
|
|
------------------------
|
|
-- Dom implementation --
|
|
------------------------
|
|
-- This provides a number of methods for performing operations that are
|
|
-- independent of any particular instance of the document object model.
|
|
|
|
type DOM_Implementation is private;
|
|
-- There are multiple implementations of DOM.
|
|
-- They can be specialized for some special cases (HTML, Stylesheets,...)
|
|
|
|
function Has_Feature
|
|
(Implementation : DOM_Implementation;
|
|
Feature : DOM_String;
|
|
Version : String := "2.0") return Boolean;
|
|
-- Return TRUE if this implementation of DOM has the Feature.
|
|
|
|
function Create_Document
|
|
(Implementation : DOM_Implementation;
|
|
NameSpace_URI : DOM_String := "";
|
|
Qualified_Name : DOM_String := "";
|
|
Doc_Type : Node := null;
|
|
Symbols : Sax.Utils.Symbol_Table := Sax.Utils.No_Symbol_Table)
|
|
return Node;
|
|
-- Create an new document with its element.
|
|
-- Note that NameSpace_URI can be the empty string if you do not want
|
|
-- to use namespaces.
|
|
-- The Document Type Definition can be null if there is none associated
|
|
-- with the document.
|
|
-- Wrong_Document_Err is raised if Doc_Type has already been used for
|
|
-- another document.
|
|
-- Symbols should be used to specify the symbol table used by the parser
|
|
-- that generates the DOM. It is needed because the various string elements
|
|
-- in the tree are represented as symbols and the correct symbol table must
|
|
-- be specified. You can get it from the parser itself by using
|
|
-- Get_Symbol_Table. Optionally, you can pass an explicit No_Symbol_Table
|
|
-- to create one automatically. It is recommended to share the table with
|
|
-- the parser whenever possible for maximum efficient.
|
|
-- In general, the document is created from the Start_Document callback
|
|
-- of a tree_reader, so the simplest is to call the inherited
|
|
-- Start_Document.
|
|
|
|
procedure Set_Node_List_Growth_Factor (Factor : Float);
|
|
-- Set the growth factor, see Default_Node_List_Growth_Factor
|
|
|
|
--------------------
|
|
-- Dom exceptions --
|
|
--------------------
|
|
-- The following exceptions are declared in the DOM interface. If we
|
|
-- were to follow exactly the interface, we should a single exception to
|
|
-- which we associate an integer code. It seems easier to provide one
|
|
-- exception for each case. However, we kept the standard names.
|
|
|
|
Index_Size_Err : exception;
|
|
-- If Index or size is invalid (negative or greated than max value).
|
|
|
|
Domstring_Size_Err : exception;
|
|
-- If the specified range of text does not fit into a DomString.
|
|
|
|
Hierarchy_Request_Err : exception;
|
|
-- If a node is inserted somewhere it doesn't belong.
|
|
|
|
Wrong_Document_Err : exception;
|
|
-- If a node is used with a document other than its own.
|
|
|
|
Invalid_Character_Err : exception;
|
|
-- If an invalid character is used, for instance in a name.
|
|
|
|
No_Data_Allowed_Err : exception;
|
|
-- If data is specified for a node that doesn't support data.
|
|
|
|
No_Modification_Allowed_Err : exception;
|
|
-- If an attempt is made to modify a read-only object.
|
|
|
|
Not_Found_Err : exception;
|
|
-- If an attempt is made to reference a node in a concept where it doesn't
|
|
-- exist.
|
|
|
|
Not_Supported_Err : exception;
|
|
-- If the implementation does not support the type of object requested.
|
|
|
|
Inuse_Attribute_Err : exception;
|
|
-- If an attempt is made to add an attribute that is already used.
|
|
|
|
Invalid_State_Err : exception;
|
|
-- If an attempt is made to use an object that is not or no longer
|
|
-- available.
|
|
|
|
Syntax_Err : exception;
|
|
-- If an invalid string is specified.
|
|
|
|
Invalid_Modification_Err : exception;
|
|
-- If an attempt is made to modify the type of the underlying object.
|
|
|
|
Namespace_Err : exception;
|
|
-- If an attempt is made to create or modify an object in a way
|
|
-- incompatible with the namespace.
|
|
|
|
Invalid_Access_Err : exception;
|
|
-- If a parameter or an operation is not supported by the underlying
|
|
-- object.
|
|
|
|
private
|
|
|
|
type DOM_Implementation is null record;
|
|
|
|
type Node_Array is array (Natural range <>) of Node;
|
|
type Node_Array_Access is access Node_Array;
|
|
|
|
procedure Free is new Ada.Unchecked_Deallocation
|
|
(Node_Array, Node_Array_Access);
|
|
|
|
type Node_List is record
|
|
Items : Node_Array_Access := null;
|
|
Last : Integer := -1;
|
|
-- The index of the last significant element in Items
|
|
end record;
|
|
|
|
Null_List : constant Node_List := (null, -1);
|
|
|
|
-- Not the most efficient way to implement a hash-table, but these are
|
|
-- generally short lists anyway (attributes,...)
|
|
type Named_Node_Map is new Node_List;
|
|
Null_Node_Map : constant Named_Node_Map := (null, -1);
|
|
|
|
------------------
|
|
-- Nodes htable --
|
|
------------------
|
|
|
|
type Node_String is record
|
|
N : Node;
|
|
Key : Sax.Symbols.Symbol;
|
|
end record;
|
|
No_Node_String : constant Node_String := (null, Sax.Symbols.No_Symbol);
|
|
|
|
procedure Free (N : in out Node_String);
|
|
function Get_Key (N : Node_String) return Sax.Symbols.Symbol;
|
|
pragma Inline (Free, Get_Key);
|
|
|
|
package Nodes_Htable is new Sax.HTable
|
|
(Element => Node_String,
|
|
Empty_Element => No_Node_String,
|
|
Free => Free,
|
|
Key => Sax.Symbols.Symbol,
|
|
Get_Key => Get_Key,
|
|
Hash => Sax.Symbols.Hash,
|
|
Equal => Sax.Symbols."=");
|
|
type Nodes_Htable_Access is access Nodes_Htable.HTable;
|
|
|
|
-------------------
|
|
-- Node_Name_Def --
|
|
-------------------
|
|
-- Attributes and Elements share the same kind description. These are
|
|
-- grouped in the same type for ease of use
|
|
|
|
type Node_Name_Def is record
|
|
Prefix : Sax.Symbols.Symbol;
|
|
Local_Name : Sax.Symbols.Symbol;
|
|
Namespace : Sax.Symbols.Symbol;
|
|
end record;
|
|
No_Node_Name : constant Node_Name_Def :=
|
|
(Prefix => Sax.Symbols.No_Symbol,
|
|
Local_Name => Sax.Symbols.No_Symbol,
|
|
Namespace => Sax.Symbols.No_Symbol);
|
|
|
|
function Qualified_Name (N : Node_Name_Def) return DOM_String;
|
|
pragma Inline (Qualified_Name);
|
|
-- Return the qualified name of N
|
|
|
|
procedure Set_Prefix
|
|
(N : in out Node_Name_Def; Prefix : Sax.Symbols.Symbol);
|
|
pragma Inline (Set_Prefix);
|
|
-- Return or set the prefix of N
|
|
|
|
function From_Qualified_Name
|
|
(Doc : Document;
|
|
Symbols : Sax.Utils.Symbol_Table;
|
|
Name : Sax.Symbols.Symbol;
|
|
Namespace : Sax.Symbols.Symbol := Sax.Symbols.No_Symbol)
|
|
return Node_Name_Def;
|
|
-- Build a node name from its qualified name. This is shared if
|
|
-- Shared_Node_Names is True.
|
|
-- Symbols is the symbol table in which Name and Namespace were created.
|
|
|
|
-----------------
|
|
-- Node_Record --
|
|
-----------------
|
|
|
|
type Node_Record (Node_Type : Node_Types) is record
|
|
Parent_Is_Owner : Boolean;
|
|
-- If True, the Parent node points to the owner document, not to the
|
|
-- real parent in the tree (which is null).
|
|
-- This boolean doesn't increase the size of this record, since because
|
|
-- of alignment issues Node_Type already occupies more space than it
|
|
-- really needs.
|
|
|
|
Parent : Node;
|
|
case Node_Type is
|
|
when Element_Node =>
|
|
Name : Node_Name_Def;
|
|
Children : Node_List;
|
|
Attributes : Named_Node_Map;
|
|
|
|
when Attribute_Node =>
|
|
Attr_Name : Node_Name_Def;
|
|
Attr_Value : Sax.Symbols.Symbol;
|
|
|
|
Owner_Element : Node;
|
|
-- Generally an Element, but it can be a Document if the attribute
|
|
-- hasn't been associated yet.
|
|
|
|
Is_Id : Boolean := False;
|
|
Specified : Boolean := False;
|
|
-- ??? In fact, attributes can have children (text or
|
|
-- entity_reference).
|
|
|
|
when Text_Node =>
|
|
Text : DOM_String_Access;
|
|
|
|
when Cdata_Section_Node =>
|
|
Cdata : DOM_String_Access;
|
|
|
|
when Entity_Reference_Node =>
|
|
Entity_Reference_Name : Sax.Symbols.Symbol;
|
|
|
|
when Entity_Node =>
|
|
Entity_Name : Sax.Symbols.Symbol;
|
|
-- ??? Allows children for the substitution of the entity
|
|
|
|
when Processing_Instruction_Node =>
|
|
Target : Sax.Symbols.Symbol;
|
|
Pi_Data : Sax.Symbols.Symbol;
|
|
|
|
when Comment_Node =>
|
|
Comment : DOM_String_Access;
|
|
|
|
when Document_Node =>
|
|
Symbols : Sax.Utils.Symbol_Table;
|
|
-- Keep a handle on the symbol table to ensure the symbols remain
|
|
-- valid while the tree exists
|
|
|
|
Doc_Children : Node_List;
|
|
Doc_Type : Node;
|
|
Implementation : DOM_Implementation;
|
|
Ids : Nodes_Htable_Access;
|
|
|
|
when Document_Type_Node =>
|
|
Document_Type_Name : DOM_String_Access;
|
|
Doc_Type_Children : Node_List;
|
|
|
|
when Document_Fragment_Node =>
|
|
Doc_Frag_Children : Node_List;
|
|
|
|
when Notation_Node =>
|
|
Public_ID : DOM_String_Access;
|
|
System_ID : DOM_String_Access;
|
|
end case;
|
|
end record;
|
|
|
|
procedure Append (List : in out Node_List; N : Node);
|
|
-- Insert N as the last element in List
|
|
|
|
procedure Remove
|
|
(List : in out Node_List;
|
|
N : Node;
|
|
Success : out Boolean);
|
|
-- Remove N from the list
|
|
-- N must be an element of List, this is not checked.
|
|
|
|
procedure Document_Add_Id
|
|
(Doc : Document;
|
|
Id : Sax.Symbols.Symbol;
|
|
Elem : Element);
|
|
-- Store in the document as fast access to Elem by its ID
|
|
|
|
procedure Document_Remove_Id
|
|
(Doc : Document;
|
|
Id : Sax.Symbols.Symbol);
|
|
-- Remove an ID associated with Elem in the fast htable access
|
|
|
|
end DOM.Core;
|