├── LICENSE.md
├── README.md
├── docs
├── quick_start.md
└── reference
│ └── node_types.md
├── tests
├── conf.lua
├── main.lua
└── player.xml
└── xml
├── dom
├── attribute.lua
├── cdata.lua
├── comment.lua
├── document.lua
├── documentimplimentation.lua
├── documenttype.lua
├── domparser.lua
├── element.lua
├── namednodemap.lua
├── node.lua
├── nodelist.lua
├── processinginstruction.lua
└── text.lua
├── dtd
├── dtdparser.lua
└── schemas
│ ├── html_401_frameset.lua
│ ├── html_401_strict.lua
│ ├── html_401_transitional.lua
│ ├── mathml_20.lua
│ ├── xhtml_10_frameset.lua
│ ├── xhtml_10_strict.lua
│ ├── xhtml_10_transitional.lua
│ └── xhtml_11.lua
├── init.lua
└── lib
├── upperclass.lua
└── utils.lua
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Regan Laitila
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | lua-libxml
2 | ==========
3 |
4 | Lua XML LIbrary for Love2d and Lua 5.x
5 |
--------------------------------------------------------------------------------
/docs/quick_start.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rdlaitila/lua-libxml/126d1ea79089719506fa71cd886fa2275a237e21/docs/quick_start.md
--------------------------------------------------------------------------------
/docs/reference/node_types.md:
--------------------------------------------------------------------------------
1 | # Node Types
2 |
3 | ```lua
4 | local libxml = require('libxml.init')
5 |
6 | local document = libxml.dom.Document()
7 |
8 | local node = libxml.dom.Node()
9 |
10 | local element = libxml.dom.Element("mytag")
11 |
12 | print(document.nodeName, node.nodeName, element.nodeName)
13 | print(document.nodeType, node.nodeType, element.nodeType)
14 | ```
15 |
16 | The following table lists the different W3C node types, and which node types they may have as children:
17 |
18 |
19 |
20 | Node Type |
21 | Description |
22 | Children |
23 |
24 |
25 | Document |
26 | Represents the entire document (the root-node of the DOM tree) |
27 | Element (max. one), ProcessingInstruction, Comment, DocumentType |
28 |
29 |
30 | DocumentFragment |
31 | Represents a "lightweight" Document object, which
32 | can hold a portion of a document |
33 | Element, ProcessingInstruction, Comment, Text, CDATASection,
34 | EntityReference |
35 |
36 |
37 | DocumentType |
38 | Provides an interface to the entities defined for the
39 | document |
40 | None |
41 |
42 |
43 | ProcessingInstruction |
44 | Represents a processing instruction |
45 | None |
46 |
47 |
48 | EntityReference |
49 | Represents an entity reference |
50 | Element, ProcessingInstruction, Comment, Text, CDATASection,
51 | EntityReference |
52 |
53 |
54 | Element |
55 | Represents an element |
56 | Element, Text, Comment, ProcessingInstruction, CDATASection,
57 | EntityReference |
58 |
59 |
60 | Attr |
61 | Represents an attribute |
62 | Text, EntityReference |
63 |
64 |
65 | Text |
66 | Represents textual content in an element
67 | or attribute |
68 | None |
69 |
70 |
71 | CDATASection |
72 | Represents a CDATA section in a document (text that will
73 | NOT be parsed by a parser) |
74 | None |
75 |
76 |
77 | Comment |
78 | Represents a comment |
79 | None |
80 |
81 |
82 | Entity |
83 | Represents an entity |
84 | Element, ProcessingInstruction, Comment, Text, CDATASection,
85 | EntityReference |
86 |
87 |
88 | Notation |
89 | Represents a notation declared in the DTD |
90 | None |
91 |
92 |
93 |
94 | # Node Types - Return Values
95 |
96 | The following table lists what the nodeName and the nodeValue properties will return for each node type:
97 |
98 |
99 |
100 | Node Type |
101 | nodeName returns |
102 | nodeValue returns |
103 |
104 |
105 | Document |
106 | #document |
107 | null |
108 |
109 |
110 | DocumentFragment |
111 | #document fragment |
112 | null |
113 |
114 |
115 | DocumentType |
116 | doctype name |
117 | null |
118 |
119 |
120 | EntityReference |
121 | entity reference name |
122 | null |
123 |
124 |
125 | Element |
126 | element name |
127 | null |
128 |
129 |
130 | Attr |
131 | attribute name |
132 | attribute value |
133 |
134 |
135 | ProcessingInstruction |
136 | target |
137 | content of node |
138 |
139 |
140 | Comment |
141 | #comment |
142 | comment text |
143 |
144 |
145 | Text |
146 | #text |
147 | content of node |
148 |
149 |
150 | CDATASection |
151 | #cdata-section |
152 | content of node |
153 |
154 |
155 | Entity |
156 | entity name |
157 | null |
158 |
159 |
160 | Notation |
161 | notation name |
162 | null |
163 |
164 |
165 |
166 | # NodeTypes - Named Constants
167 |
168 |
169 |
170 | NodeType |
171 | Named Constant |
172 |
173 |
174 | 1 |
175 | ELEMENT_NODE |
176 |
177 |
178 | 2 |
179 | ATTRIBUTE_NODE |
180 |
181 |
182 | 3 |
183 | TEXT_NODE |
184 |
185 |
186 | 4 |
187 | CDATA_SECTION_NODE |
188 |
189 |
190 | 5 |
191 | ENTITY_REFERENCE_NODE |
192 |
193 |
194 | 6 |
195 | ENTITY_NODE |
196 |
197 |
198 | 7 |
199 | PROCESSING_INSTRUCTION_NODE |
200 |
201 |
202 | 8 |
203 | COMMENT_NODE |
204 |
205 |
206 | 9 |
207 | DOCUMENT_NODE |
208 |
209 |
210 | 10 |
211 | DOCUMENT_TYPE_NODE |
212 |
213 |
214 | 11 |
215 | DOCUMENT_FRAGMENT_NODE |
216 |
217 |
218 | 12 |
219 | NOTATION_NODE |
220 |
221 |
--------------------------------------------------------------------------------
/tests/conf.lua:
--------------------------------------------------------------------------------
1 | function love.conf(t)
2 | t.console = true
3 | end
--------------------------------------------------------------------------------
/tests/main.lua:
--------------------------------------------------------------------------------
1 | libxml = require('xml.init')
2 |
3 | local elements = {}
4 | for a=1, 100000 do
5 | table.insert(elements, libxml.dom.Element("div"))
6 | end
--------------------------------------------------------------------------------
/tests/player.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/xml/dom/attribute.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 |
5 | --
6 | -- Define class
7 | --
8 | local Attribute = upperclass:define("DOMAttribute", DOMNode)
9 |
10 | --
11 | -- Returns true if the attribute is known to be of type ID, otherwise it returns false
12 | --
13 | property : isId {
14 | false;
15 | get='public';
16 | set='private';
17 | }
18 |
19 | --
20 | -- Returns the element node the attribute is attached to
21 | --
22 | property : ownerElement {
23 | nil;
24 | get='public';
25 | set='public';
26 | type='any';
27 | }
28 |
29 | --
30 | -- Class Constructor
31 | --
32 | function private:__construct(ATTR_NAME, ATTR_VALUE)
33 | self:__constructparent(2)
34 |
35 | self.nodeName = ATTR_NAME
36 | self.nodeValue = ATTR_VALUE
37 |
38 | if ATTR_NAME == "id" then
39 | self.isId = true
40 | end
41 | end
42 |
43 | --
44 | -- __index metamethod
45 | --
46 | function private:__index(KEY)
47 | if KEY == 'name' then
48 | return self.nodeName
49 | elseif KEY == 'value' then
50 | return self.nodeValue
51 | end
52 |
53 | return UPPERCLASS_DEFAULT_BEHAVIOR
54 | end
55 |
56 | --
57 | -- __Newindex metamethod
58 | --
59 | function private:__newindex(KEY, VALUE)
60 | if KEY == 'name' then
61 | self.nodeName = VALUE
62 | return
63 | elseif KEY == 'value' then
64 | self.nodeValue = VALUE
65 | return
66 | end
67 |
68 | return UPPERCLASS_DEFAULT_BEHAVIOR
69 | end
70 |
71 | --
72 | -- Compile class
73 | --
74 | return upperclass:compile(Attribute)
75 |
76 |
--------------------------------------------------------------------------------
/xml/dom/cdata.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 |
5 | --
6 | -- Define class
7 | --
8 | local Characterdata = upperclass:define("DOMCDATA", DOMNode)
9 |
10 | --
11 | -- Sets or returns the text of this node
12 | --
13 | property : data {
14 | nil;
15 | get='public';
16 | set='public';
17 | type='string';
18 | }
19 |
20 | --
21 | -- Class constructor
22 | --
23 | function private:__construct(DATA)
24 | self:__constructparent(4)
25 | self.nodeName = "#cdata-section"
26 | self.data = DATA
27 | end
28 |
29 | --
30 | -- __index metamethod
31 | --
32 | function private:__index(KEY)
33 | if KEY == 'length' then
34 | return self.data:len()
35 | elseif KEY == 'nodeValue' then
36 | return self.data
37 | end
38 |
39 | return UPPERCLASS_DEFAULT_BEHAVIOR
40 | end
41 |
42 | --
43 | -- Appends data to the node
44 | --
45 | function public:appendData(DATA)
46 | error("Method Not Yet Implimented")
47 | end
48 |
49 | --
50 | -- Deletes data from the node
51 | --
52 | function public:deleteData(DATA)
53 | error("Method Not Yet Implimented")
54 | end
55 |
56 | --
57 | -- Inserts data into the node
58 | --
59 | function public:insertData(DATA)
60 | error("Method Not Yet Implimented")
61 | end
62 |
63 | --
64 | -- Replaces data in the node
65 | --
66 | function public:replaceData()
67 | error("Method Not Yet Implimented")
68 | end
69 |
70 | --
71 | -- Splits the CDATA node into two nodes
72 | --
73 | function public:splitText()
74 | error("Method Not Yet Implimented")
75 | end
76 |
77 | --
78 | -- Extracts data from the node
79 | --
80 | function public:substringData()
81 | error("Method Not Yet Implimented")
82 | end
83 |
84 | --
85 | -- Compile class
86 | --
87 | return upperclass:compile(Characterdata)
--------------------------------------------------------------------------------
/xml/dom/comment.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMCDATA = require(LIBXML_REQUIRE_PATH..'dom.cdata')
4 |
5 | --
6 | -- Define class
7 | --
8 | local Comment = upperclass:define("DOMComment", DOMCDATA)
9 |
10 | --
11 | -- Class constructor
12 | --
13 | function private:__construct(DATA)
14 | self:__constructparent(DATA)
15 | self.nodeType = 8
16 | self.nodeName = "#comment"
17 | end
18 |
19 | --
20 | -- Compile class
21 | --
22 | return upperclass:compile(Comment)
--------------------------------------------------------------------------------
/xml/dom/document.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 | local DOMAttribute = require(LIBXML_REQUIRE_PATH..'dom.attribute')
5 | local DOMCDATA = require(LIBXML_REQUIRE_PATH..'dom.cdata')
6 | local DOMComment = require(LIBXML_REQUIRE_PATH..'dom.comment')
7 | local DOMElement = require(LIBXML_REQUIRE_PATH..'dom.element')
8 | local DOMText = require(LIBXML_REQUIRE_PATH..'dom.text')
9 |
10 | --
11 | -- Define class
12 | --
13 | local Document = upperclass:define('DOMDocument', DOMNode)
14 |
15 | --
16 | -- Specifies whether downloading of an XML file should be handled asynchronously or not
17 | --
18 | property : async {
19 | false;
20 | get='public';
21 | set='public';
22 | }
23 |
24 | --
25 | -- Returns the Document Type Declaration associated with the document
26 | --
27 | property : doctype {
28 | nil;
29 | get='public';
30 | set='private';
31 | type='any';
32 | }
33 |
34 | --
35 | -- Returns the root node of the document
36 | --
37 | property : documentElement {
38 | nil;
39 | get='public';
40 | set='protected';
41 | type='any';
42 | }
43 |
44 | --
45 | -- Sets or returns the location of the document
46 | --
47 | property : documentURI {
48 | nil;
49 | get='public';
50 | set='public';
51 | type='string';
52 | }
53 |
54 | --
55 | -- Returns the configuration used when normalizeDocument() is invoked
56 | --
57 | property : domConfig {
58 | nil;
59 | get='public';
60 | set='private';
61 | type='any';
62 | }
63 |
64 | --
65 | -- Returns the DOMImplementation object that handles this document
66 | --
67 | property : implementation {
68 | nil;
69 | get='public';
70 | set='private';
71 | type='any';
72 | }
73 |
74 | --
75 | -- Returns the encoding used for the document (when parsing)
76 | --
77 | property : inputEncoding {
78 | nil;
79 | get='public';
80 | set='private';
81 | type='any';
82 | }
83 |
84 | --
85 | -- Sets or returns whether error-checking is enforced or not
86 | --
87 | property : strictErrorChecking {
88 | true;
89 | get='public';
90 | set='public';
91 | }
92 |
93 | --
94 | -- Returns the XML encoding of the document
95 | --
96 | property : xmlEncoding {
97 | nil;
98 | get='public';
99 | set='public';
100 | type='string';
101 | }
102 |
103 | --
104 | -- Sets or returns whether the document is standalone
105 | --
106 | property : xmlStandalone {
107 | nil;
108 | get='public';
109 | set='public';
110 | type='string'
111 | }
112 |
113 | --
114 | -- Sets or returns the XML version of the document
115 | --
116 | property : xmlVersion {
117 | nil;
118 | get='public';
119 | set='public';
120 | type='string';
121 | }
122 |
123 | --
124 | -- Class constructor
125 | --
126 | function private:__construct()
127 | self:__constructparent(9)
128 | self.nodeName = "#document"
129 | self.ownerDocument = self
130 | end
131 |
132 | --
133 | -- Adopts a node from another document to this document, and returns the adopted node
134 | --
135 | function public:adoptNode(SOURCENODE)
136 | error("Method Not Yet Implimented")
137 | end
138 |
139 | --
140 | -- Creates an attribute node with the specified name, and returns the new Attr object
141 | --
142 | function public:createAttribute(NAME)
143 | return DOMAttribute(NAME)
144 | end
145 |
146 | --
147 | -- Creates an attribute node with the specified name and namespace, and returns the new Attr object
148 | --
149 | function public:createAttributeNS(URI, NAME)
150 | error("Method Not Yet Implimented")
151 | end
152 |
153 | --
154 | -- Creates a CDATA section node
155 | --
156 | function public:createCDATASection(DATA)
157 | return DOMCDATA(DATA)
158 | end
159 |
160 | --
161 | -- Creates a comment node
162 | --
163 | function public:createComment(DATA)
164 | return DOMComment(DATA)
165 | end
166 |
167 | --
168 | -- Creates an empty DocumentFragment object, and returns it
169 | --
170 | function public:createDocumentFragment()
171 | error("Method Not Yet Implimented")
172 | end
173 |
174 | --
175 | -- Creates an element node
176 | --
177 | function public:createElement(TAGNAME)
178 | return DOMElement(TAGNAME)
179 | end
180 |
181 | --
182 | -- Creates an element node with a specified namespace
183 | --
184 | function public:createElementNS()
185 | error("Method Not Yet Implimented")
186 | end
187 |
188 | --
189 | -- Creates an EntityReference object, and returns it
190 | --
191 | function public:createEntityReference(NAME)
192 | error("Method Not Yet Implimented")
193 | end
194 |
195 | --
196 | -- Creates a ProcessingInstruction object, and returns it
197 | --
198 | function public:createProcessingInstruction(TARGET, DATA)
199 | error("Method Not Yet Implimented")
200 | end
201 |
202 | --
203 | -- Creates a text node
204 | --
205 | function public:createTextNode(TEXT)
206 | return DOMText(TEXT)
207 | end
208 |
209 | --
210 | -- Imports a node from another document to this document. This method creates a new copy of the source node. If the deep parameter is set to true, it imports all children of the specified node. If set to false, it imports only the node itself. This method returns the imported node
211 | --
212 | function public:importNode(NODE, DEEP)
213 | error("Method Not Yet Implimented")
214 | end
215 |
216 | --
217 | -- normalizeDocument()
218 | --
219 | function public:normalizeDocument()
220 | error("Method Not Yet Implimented")
221 | end
222 |
223 | --
224 | -- Renames an element or attribute node
225 | --
226 | function public:renameNode()
227 | error("Method Not Yet Implimented")
228 | end
229 |
230 | --
231 | -- Compile Class
232 | --
233 | return upperclass:compile(Document)
--------------------------------------------------------------------------------
/xml/dom/documentimplimentation.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 |
4 | --
5 | -- Define class
6 | --
7 | local DocumentImplimentation = upperclass:define("DOMDocumentImplimentation")
8 |
9 | --
10 | -- Creates a new DOM Document object of the specified doctype
11 | --
12 | function public:createDocument(NSURI, NAME, DOCTYPE)
13 | error("Method Not Yet Implimented")
14 | end
15 |
16 | --
17 | -- Creates an empty DocumentType node
18 | --
19 | function public:createDocumentType(NAME, PUBID, SYSTEMID)
20 | error("Method Not Yet Implimented")
21 | end
22 |
23 | --
24 | -- Returns an object which implements the APIs of the specified feature and version, if the is any
25 | --
26 | function public:getFeature(FEATURE, VERSION)
27 | error("Method Not Yet Implimented")
28 | end
29 |
30 | --
31 | -- Checks whether the DOM implementation implements a specific feature and version
32 | --
33 | function public:hasFeature(FEATURE, VERSION)
34 | error("Method Not Yet Implimented")
35 | end
36 |
37 | --
38 | -- Compile class
39 | --
40 | return upperclass:compile(DocumentImplimentation)
--------------------------------------------------------------------------------
/xml/dom/documenttype.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 | local DOMNamedNodeMap = require(LIBXML_REQUIRE_PATH..'dom.namednodemap')
5 |
6 | --
7 | -- Define class
8 | --
9 | local DocumentType = upperclass:define("DOMDocumentType", DOMNode)
10 |
11 | --
12 | -- Returns a NamedNodeMap containing the entities declared in the DTD
13 | --
14 | property : entities {
15 | nil;
16 | get='public';
17 | set='private';
18 | type='any';
19 | }
20 |
21 | --
22 | -- Returns the internal DTD as a string
23 | --
24 | property : internalSubset {
25 | nil;
26 | get='public';
27 | set='private';
28 | type='string';
29 | }
30 |
31 | --
32 | -- Returns the name of the DTD
33 | --
34 | property : name {
35 | nil;
36 | get='public';
37 | set='private';
38 | type='string';
39 | }
40 |
41 | --
42 | -- Returns a NamedNodeMap containing the notations declared in the DTD
43 | --
44 | property : notations {
45 | nil;
46 | get='public';
47 | set='private';
48 | type='any';
49 | }
50 |
51 | --
52 | -- Class constructor
53 | --
54 | function private:__construct()
55 | self:__constructparent(10)
56 | self.entities = DOMNamedNodeMap()
57 | self.notations = DOMNamedNodeMap()
58 | end
59 |
60 | --
61 | -- __index metamethod
62 | --
63 | function private:__index(KEY)
64 | if KEY == 'nodeName' then
65 | return self.name
66 | end
67 |
68 | return UPPERCLASS_DEFAULT_BEHAVIOR
69 | end
70 |
71 | --
72 | -- Compile class
73 | --
74 | return upperclass:compile(DocumentType)
--------------------------------------------------------------------------------
/xml/dom/domparser.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMDocument = require(LIBXML_REQUIRE_PATH..'dom.document')
4 | local DOMText = require(LIBXML_REQUIRE_PATH..'dom.text')
5 | local DOMElement = require(LIBXML_REQUIRE_PATH..'dom.element')
6 | local DOMComment = require(LIBXML_REQUIRE_PATH..'dom.comment')
7 |
8 | --
9 | -- Define class
10 | --
11 | local DOMParser = upperclass:define('DOMParser')
12 |
13 | --
14 | -- Parse Debug
15 | --
16 | public.parsedebug = false
17 |
18 | --
19 | -- Source Text
20 | --
21 | private.srcText = ""
22 |
23 | --
24 | -- Open Nodes
25 | --
26 | private.openNodes = nil
27 |
28 | --
29 | -- Text Node Character Buffer
30 | --
31 | private.textNodeCharBuffer = ""
32 |
33 | --
34 | -- DOM Document
35 | --
36 | private.document = nil
37 |
38 | --
39 | -- Last Node Reference
40 | --
41 | private.lastNodeReference = nil
42 |
43 | --
44 | -- Class Constructor
45 | --
46 | function private:__construct()
47 | self.document = DOMDocument()
48 | self.lastNodeReference = self.document
49 | self.openNodes = {}
50 | end
51 |
52 | --
53 | -- ParseFromString
54 | --
55 | function public:parseFromString(XML_STRING)
56 | local charindex = 1
57 |
58 | self.srcText = string.gsub(XML_STRING, "[\t]", "")
59 |
60 | --self.srcText = string.gsub(pSrcText, "[\r\n]", "")
61 |
62 | while charindex <= self.srcText:len() do
63 | if self:char(charindex) == "<" then
64 | if self.textNodeCharBuffer:len() > 0 then
65 | self:openNode(charindex, "text")
66 | elseif self:char(charindex + 1) == "/" then
67 | charindex = self:closeNode(charindex)
68 | elseif self.srcText:sub(charindex+1, charindex+3) == "!--" then
69 | charindex = self:openNode(charindex, "comment")
70 | elseif self.srcText:sub(charindex+1, charindex+8) == "![CDATA[" then
71 | charindex = self:openNode(charindex, "CDATASection")
72 | elseif self.srcText:sub(charindex+1, charindex+4) == "?xml" then
73 | charindex = self:openNode(charindex, "XMLDeclaration")
74 | else
75 | charindex = self:openNode(charindex, "tag")
76 | end
77 | else
78 | self.textNodeCharBuffer = self.textNodeCharBuffer .. self:char(charindex)
79 | charindex = charindex +1
80 | end
81 | end
82 |
83 | return self.document
84 | end
85 |
86 | --
87 | -- OpenNode
88 | --
89 | function private:openNode(NODE_INDEX, NODE_TYPE)
90 | if NODE_TYPE == "tag" then
91 | local tagContent = string.match(self.srcText, "<(.-)>", NODE_INDEX)
92 | local tagName = utils:trim(string.match(tagContent, "([%a%d]+)%s?", 1))
93 |
94 | table.insert(self.openNodes, DOMElement(tagName))
95 |
96 | -- get attributes from tagContent
97 | for matchedAttr in string.gmatch(string.sub(tagContent,tagName:len()+1), "(.-=\".-\")") do
98 | for attr, value in string.gmatch(matchedAttr, "(.-)=\"(.-)\"") do
99 | self.openNodes[#self.openNodes]:setAttribute(utils:trim(attr), utils:trim(value))
100 | end
101 | end
102 |
103 | self.lastNodeReference = self.lastNodeReference:appendChild(self.openNodes[#self.openNodes])
104 |
105 | -- check to see if the tag is self closing, else check against self.selfCloseElements
106 | if string.match(tagContent, "/$") then
107 | self.openNodes[#self.openNodes].isSelfClosing = true
108 | self:closeNode(NODE_INDEX)
109 | end
110 |
111 | return NODE_INDEX + string.match(self.srcText, "(<.->)", NODE_INDEX):len()
112 | elseif NODE_TYPE == "comment" then
113 | local commentText = string.match(self.srcText, "", NODE_INDEX)
114 |
115 | return NODE_INDEX + string.match(self.srcText, "()", NODE_INDEX):len()
116 | elseif NODE_TYPE == "text" then
117 | local text = utils:trim(self.textNodeCharBuffer)
118 | self.lastNodeReference:appendChild(DOMText(text))
119 | self.textNodeCharBuffer = ""
120 | elseif NODE_TYPE == "CDATASection" then
121 | local cdataText = string.match(self.srcText, "", pIndex)
122 | local newNode = libxml.dom.createCharacterData(cdataText)
123 | self.lastNodeReference:appendChild(newNode)
124 | return NODE_INDEX + string.match(self.srcText, "()", NODE_INDEX):len()
125 | elseif NODE_TYPE == "XMLDeclaration" then
126 | local declarationContent = string.match(self.srcText, "", NODE_INDEX)
127 |
128 | -- get attributes from tagContent
129 | for matchedAttr in string.gmatch(declarationContent, "(.-=\".-\")") do
130 | for attr, value in string.gmatch(matchedAttr, "(.-)=\"(.-)\"") do
131 | if utils:trim(attr:lower()) == "version" then
132 | self.document.xmlVersion = value
133 | elseif utils:trim(attr:lower()) == "encoding" then
134 | self.document.xmlEncoding = value
135 | elseif utils:trim(attr:lower()) == "standalone" then
136 | self.document.xmlStandalone = value
137 | end
138 | end
139 | end
140 |
141 | return string.match(self.srcText, "", NODE_INDEX):len()
142 | end
143 | end
144 |
145 | --
146 | -- CloseNode
147 | --
148 | function private:closeNode(NODE_INDEX)
149 | local tagname = utils:trim(string.match(self.srcText, "/?([%a%d]+)%s?", NODE_INDEX))
150 | if utils:trim(self.openNodes[#self.openNodes].tagName:upper()) == utils:trim(tagname):upper() then
151 | table.remove(self.openNodes, #self.openNodes)
152 | self.lastNodeReference = self.lastNodeReference.parentNode
153 | end
154 | return NODE_INDEX + string.match(self.srcText, "(<.->)", NODE_INDEX):len()
155 | end
156 |
157 | --
158 | -- Char
159 | --
160 | function private:char(INDEX)
161 | return self.srcText:sub(INDEX, INDEX)
162 | end
163 |
164 | --
165 | -- Compile
166 | --
167 | return upperclass:compile(DOMParser)
--------------------------------------------------------------------------------
/xml/dom/element.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 | local DOMNodeList = require(LIBXML_REQUIRE_PATH..'dom.nodelist')
5 | local DOMAttribute = require(LIBXML_REQUIRE_PATH..'dom.attribute')
6 |
7 | --
8 | -- Define class
9 | --
10 | local Element = upperclass:define("DOMElement", DOMNode)
11 |
12 | --
13 | -- Is this element a self closing tag
14 | --
15 | property : isSelfClosing {
16 | false;
17 | get='public';
18 | set='public';
19 | type='boolean';
20 | }
21 |
22 | --
23 | -- Returns the type information associated with the element
24 | --
25 | property : schemaTypeInfo {
26 | nil;
27 | get='public';
28 | set='private';
29 | type='any';
30 | }
31 |
32 | --
33 | -- Class constructor
34 | --
35 | function private:__construct(TAGNAME)
36 | self:__constructparent(1)
37 | self.nodeName = utils:trim(TAGNAME)
38 | end
39 |
40 | --
41 | -- __index metamethod
42 | --
43 | function private:__index(KEY)
44 | if KEY == 'tagName' then
45 | return self.nodeName
46 | end
47 |
48 | return UPPERCLASS_DEFAULT_BEHAVIOR
49 | end
50 |
51 | --
52 | -- Returns the value of an attribute
53 | --
54 | function public:getAttribute(ATTRIBUTE_NAME)
55 | local attrnode = self:getAttributeNode(ATTRIBUTE_NAME)
56 | if attrnode ~= nil then
57 | return attrnode.value
58 | end
59 | end
60 |
61 | --
62 | -- Returns the value of an attribute (with a namespace)
63 | --
64 | function public:getAttributeNS()
65 | error("Method Not Yet Implimented")
66 | end
67 |
68 | --
69 | -- Returns an attribute node as an Attribute object
70 | --
71 | function public:getAttributeNode(ATTRIBUTE_NAME)
72 | for a=1, self.attributes.length do
73 | if self.attributes[a].name == utils:trim(ATTRIBUTE_NAME) then
74 | return self.attributes[a]
75 | end
76 | end
77 | end
78 |
79 | --
80 | -- Returns an attribute node (with a namespace) as an Attribute object
81 | --
82 | function public:getAttributeNodeNS()
83 | error("Method Not Yet Implimented")
84 | end
85 |
86 | --
87 | -- Adds a new attribute
88 | --
89 | function public:setAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE)
90 | for a=1, self.attributes.length do
91 | if self.attributes[a].name == utils:trim(ATTRIBUTE_NAME) then
92 | self.attributes[a].value = ATTRIBUTE_VALUE
93 | return
94 | end
95 | end
96 |
97 | local newattribute = DOMAttribute(utils:trim(ATTRIBUTE_NAME), ATTRIBUTE_VALUE)
98 | return self.attributes:setNamedItem(newattribute)
99 | end
100 |
101 | --
102 | -- Compile class
103 | --
104 | return upperclass:compile(Element)
--------------------------------------------------------------------------------
/xml/dom/namednodemap.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNodeList = require(LIBXML_REQUIRE_PATH..'dom.nodelist')
4 |
5 | --
6 | -- Define class
7 | --
8 | local NamedNodeMap = upperclass:define("DOMNamedNodeMap", DOMNodeList)
9 |
10 | --
11 | -- Returns the node with the specific name
12 | --
13 | function public:getNamedItem(NAME)
14 | for a=1, self.length do
15 | if self.nodes[a].nodeName == NAME then
16 | return self.nodes[a]
17 | end
18 | end
19 | end
20 |
21 | --
22 | -- Returns the node with the specific name and namespace
23 | --
24 | function public:getNamedItemNS(NS, NAME)
25 | error("Method Not Yet Implimented")
26 | end
27 |
28 | --
29 | -- Removes the node with the specific name
30 | --
31 | function public:removeNamedItem(NAME)
32 | local node = nil
33 | local nodeindex = nil
34 | for a=1, self.length do
35 | if self.nodes[a].nodeName == NAME then
36 | node = self.nodes[a]
37 | nodeindex = a
38 | end
39 | end
40 | table.remove(self.nodes, nodeindex)
41 | end
42 |
43 | --
44 | -- Removes the node with the specific name and namespace
45 | --
46 | function public:removeNamedItemNS(NS, NAME)
47 | error("Method Not Yet Implimented")
48 | end
49 |
50 | --
51 | -- Sets the specified node (by name)
52 | --
53 | function public:setNamedItem(ATTR_NODE)
54 | for a=1, self.length do
55 | if self.nodes[a].nodeName == ATTR_NODE.nodeName then
56 | local returnnode = self.nodes[a]
57 | self.nodes[a] = ATTR_NODE
58 | return returnnode
59 | end
60 | end
61 |
62 | table.insert(self.nodes, ATTR_NODE)
63 | end
64 |
65 | --
66 | -- Sets the specified node (by name and namespace)
67 | --
68 | function public:setNamedItemNS(NS, NAME, NODE)
69 | error("Method Not Yet Implimented")
70 | end
71 |
72 | --
73 | -- Compile class
74 | --
75 | return upperclass:compile(NamedNodeMap)
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/xml/dom/node.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNamedNodeMap = require(LIBXML_REQUIRE_PATH..'dom.namednodemap')
4 | local DOMNodeList = require(LIBXML_REQUIRE_PATH..'dom.nodelist')
5 |
6 | --
7 | -- Define class
8 | --
9 | local Node = upperclass:define('DOMNode')
10 |
11 | --
12 | -- A NamedNodeMap containing the attributes of this node
13 | --
14 | property : attributes {
15 | nil;
16 | get='public';
17 | set='protected';
18 | type='table'
19 | }
20 |
21 | --
22 | -- Returns the absolute base URI of a node
23 | --
24 | property : baseURI {
25 | "";
26 | get='public';
27 | set='protected'
28 | }
29 |
30 | --
31 | -- Returns a NodeList of child nodes for a node
32 | --
33 | property : childNodes {
34 | nil;
35 | get='public';
36 | set='protected';
37 | type='table'
38 | }
39 |
40 | --
41 | -- Returns the first child of a node
42 | --
43 | property : firstChild {
44 | nil;
45 | get='public';
46 | set='protected';
47 | type={DOMNode, DOMElement, }
48 | }
49 |
50 | --
51 | -- Returns the last child of a node
52 | --
53 | property : lastChild {
54 | nil;
55 | get='public';
56 | set='protected';
57 | type='any'
58 | }
59 |
60 | --
61 | -- Returns the local part of the name of a node
62 | --
63 | property : localName {
64 | "";
65 | get='public';
66 | set='protected'
67 | }
68 |
69 | --
70 | -- Returns the namespace URI of a node
71 | --
72 | property : namespaceURI {
73 | "";
74 | get='public';
75 | set='protected';
76 | }
77 |
78 | --
79 | -- Returns the node immediately following a node
80 | --
81 | property : nextSibling {
82 | nil;
83 | get='public';
84 | set='protected';
85 | type='any'
86 | }
87 |
88 | --
89 | -- Returns the name of a node, depending on its type
90 | --
91 | property : nodeName {
92 | nil;
93 | get='public';
94 | set='protected';
95 | type='string';
96 | }
97 |
98 | --
99 | -- Returns the type of a node
100 | --
101 | property : nodeType {
102 | 0;
103 | get='public';
104 | set='protected';
105 | }
106 |
107 | --
108 | -- Sets or returns the value of a node, depending on its type
109 | --
110 | property : nodeValue {
111 | nil;
112 | get='public';
113 | set='public';
114 | type='any'
115 | }
116 |
117 | --
118 | -- Returns the root element (document object) for a node
119 | --
120 | property : ownerDocument {
121 | nil;
122 | get='public';
123 | set='protected';
124 | type='any'
125 | }
126 |
127 | --
128 | -- Returns the parent node of a node
129 | --
130 | property : parentNode {
131 | nil;
132 | get='public';
133 | set='public';
134 | type='any'
135 | }
136 |
137 | --
138 | -- Sets or returns the namespace prefix of a node
139 | --
140 | property : prefix {
141 | nil;
142 | get='public';
143 | set='public';
144 | type='any'
145 | }
146 |
147 | --
148 | -- Returns the node immediately before a node
149 | --
150 | property : previousSibling {
151 | nil;
152 | get='public';
153 | set='protected';
154 | type='any';
155 | }
156 |
157 | --
158 | -- Sets or returns the textual content of a node and its descendants
159 | --
160 | property : textContent {
161 | nil;
162 | get='public';
163 | set='public';
164 | type='any';
165 | }
166 |
167 | --
168 | -- Class Construct
169 | --
170 | function private:__construct(NODETYPE)
171 | if type(NODETYPE) == "number" then
172 | self.nodeType = NODETYPE
173 | else
174 | error("NodeType must be a number")
175 | end
176 |
177 | self.attributes = DOMNamedNodeMap()
178 | self.childNodes = DOMNodeList()
179 | end
180 |
181 | --
182 | -- Appends a new child node to the end of the list of children of a node
183 | --
184 | function public:appendChild(NODE)
185 | NODE.parentNode = self
186 |
187 | NODE.ownerDocument = self.ownerDocument
188 |
189 | self.childNodes:add(NODE)
190 |
191 | self.firstChild = self.childNodes[1]
192 |
193 | self.lastChild = self.childNodes[self.childNodes.length]
194 |
195 | -- If this node is a document node (type 9) and the appending node is
196 | -- a element node (type 1) then set documentElement to self
197 | if self.nodeType == 9 and NODE.nodeType == 1 then
198 | self.documentElement = NODE
199 | end
200 |
201 | return NODE
202 | end
203 |
204 | --
205 | -- Clones a node
206 | --
207 | function public:cloneNode()
208 | error("Method Not Yet Implimented")
209 | end
210 |
211 | --
212 | -- Compares the placement of two nodes in the DOM hierarchy (document)
213 | --
214 | function public:compareDocumentPosition()
215 | error("Method Not Yet Implimented")
216 | end
217 |
218 | --
219 | -- Returns a DOM object which implements the specialized APIs of the specified feature and version
220 | --
221 | function public:getFeature()
222 | error("Method Not Yet Implimented")
223 | end
224 |
225 | --
226 | -- Returns the object associated to a key on a this node. The object must first have been set to this node by calling setUserData with the same key
227 | --
228 | function public:getUserData()
229 | error("Method Not Yet Implimented")
230 | end
231 |
232 | --
233 | -- Returns true if the specified node has any attributes, otherwise false
234 | --
235 | function public:hasAttributes()
236 | if self.attributes.length > 0 then
237 | return true
238 | else
239 | return false
240 | end
241 | end
242 |
243 | --
244 | -- Returns true if the specified node has any child nodes, otherwise false
245 | --
246 | function public:hasChildNodes()
247 | if self.childNodes.length > 0 then
248 | return true
249 | else
250 | return false
251 | end
252 | end
253 |
254 | --
255 | -- Inserts a new child node before an existing child node
256 | --
257 | function public:insertBefore()
258 | error("Method Not Yet Implimented")
259 | end
260 |
261 | --
262 | -- Returns whether the specified namespaceURI is the default
263 | --
264 | function public:isDefaultNamespace()
265 | error("Method Not Yet Implimented")
266 | end
267 |
268 | --
269 | -- Tests whether two nodes are equal
270 | --
271 | function public:isEqualNode()
272 | error("Method Not Yet Implimented")
273 | end
274 |
275 | --
276 | -- Tests whether the two nodes are the same node
277 | --
278 | function public:isSameNode()
279 | error("Method Not Yet Implimented")
280 | end
281 |
282 | --
283 | -- Tests whether the DOM implementation supports a specific feature and that the feature is supported by the specified node
284 | --
285 | function public:isSupported()
286 | error("Method Not Yet Implimented")
287 | end
288 |
289 | --
290 | -- Returns the namespace URI associated with a given prefix
291 | --
292 | function public:lookupNamespaceURI()
293 | error("Method Not Yet Implimented")
294 | end
295 |
296 | --
297 | -- Returns the prefix associated with a given namespace URI
298 | --
299 | function public:lookupPrefix()
300 | error("Method Not Yet Implimented")
301 | end
302 |
303 | --
304 | -- Puts all Text nodes underneath a node (including attribute nodes) into a "normal" form where only structure
305 | -- (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes,
306 | -- i.e., there are neither adjacent Text nodes nor empty Text nodes
307 | --
308 | function public:normalize()
309 | error("Method Not Yet Implimented")
310 | end
311 |
312 | --
313 | -- Removes a specified child node from the current node
314 | --
315 | function public:removeChild()
316 | error("Method Not Yet Implimented")
317 | end
318 |
319 | --
320 | -- Replaces a child node with a new node
321 | --
322 | function public:replaceChild()
323 | error("Method Not Yet Implimented")
324 | end
325 |
326 | --
327 | -- Associates an object to a key on a node
328 | --
329 | function public:setUserData()
330 | error("Method Not Yet Implimented")
331 | end
332 |
333 | --
334 | -- Returns the element that has an ID attribute with the given value. If no such element exists, it returns null
335 | --
336 | function public:getElementById(ID)
337 | error("Method Not Yet Implimented")
338 | end
339 |
340 | --
341 | -- Returns a NodeList of all elements with a specified name
342 | --
343 | function public:getElementsByTagName(TAGNAME)
344 | local nodelist = DOMNodeList()
345 | local targetElement = self
346 |
347 | if targetElement.nodeType == 1 and targetElement.tagName == TAGNAME then
348 | nodelist:add(targetElement)
349 | end
350 |
351 | if targetElement:hasChildNodes() then
352 | for a=1, targetElement.childNodes.length do
353 | local childNodes = targetElement.childNodes[a]:getElementsByTagName(TAGNAME)
354 | for b=1, childNodes.length do
355 | nodelist:add(childNodes[b])
356 | end
357 | end
358 | end
359 |
360 | return nodelist
361 | end
362 |
363 | --
364 | -- Returns a NodeList of all elements with a specified name and namespace
365 | --
366 | function public:getElementsByTagNameNS()
367 | error("Method Not Yet Implimented")
368 | end
369 |
370 | --
371 | -- Compile Class
372 | --
373 | return upperclass:compile(Node)
--------------------------------------------------------------------------------
/xml/dom/nodelist.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 |
4 | --
5 | -- Define class
6 | --
7 | local NodeList = upperclass:define("NodeList")
8 |
9 | --
10 | -- Holds a list of nodes for this NodeList
11 | --
12 | protected.nodes = nil
13 |
14 | --
15 | -- Class constructor
16 | --
17 | function private:__construct()
18 | -- generate a new nodes table
19 | self.nodes = {}
20 | end
21 |
22 | --
23 | -- __index metamethod
24 | --
25 | function private:__index(KEY)
26 | if type(KEY) == 'number' then
27 | return self:item(KEY)
28 | elseif KEY == 'length' then
29 | return #self.nodes
30 | end
31 |
32 | return UPPERCLASS_DEFAULT_BEHAVIOR
33 | end
34 |
35 | --
36 | -- Returns the node at the specified index in a node list
37 | --
38 | function public:item(INDEX)
39 | return self.nodes[INDEX] or nil
40 | end
41 |
42 | --
43 | -- Adds a node to the node list
44 | --
45 | function public:add(NODE)
46 | table.insert(self.nodes, NODE)
47 | end
48 |
49 | --
50 | -- Compile Class
51 | --
52 | return upperclass:compile(NodeList)
53 |
--------------------------------------------------------------------------------
/xml/dom/processinginstruction.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMNode = require(LIBXML_REQUIRE_PATH..'dom.node')
4 |
5 | --
6 | -- Define class
7 | --
8 | local ProcessingInstruction = upperclass:define("DOMProcessingInstruction", DOMNode)
9 |
10 | --
11 | -- Sets or returns the content of this processing instruction
12 | --
13 | property : data {
14 | nil;
15 | get='public';
16 | set='private';
17 | type='any';
18 | }
19 |
20 | --
21 | -- Returns the target of this processing instruction
22 | --
23 | property : target {
24 | nil;
25 | get='public';
26 | set='public';
27 | type='any';
28 | }
29 |
30 | --
31 | -- Class constructor
32 | --
33 | function private:__construct()
34 | self:__constructparent(7)
35 | end
36 |
37 | --
38 | -- __index metamethod
39 | --
40 | function private:__index(KEY)
41 | if KEY == 'nodeName' then
42 | return self.target
43 | elseif KEY == 'nodeValue' then
44 | return self.data
45 | end
46 |
47 | return UPPERCLASS_DEFAULT_BEHAVIOR
48 | end
49 |
50 | --
51 | -- Compile class
52 | --
53 | return upperclass:compile(ProcessingInstruction)
--------------------------------------------------------------------------------
/xml/dom/text.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 | local utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
3 | local DOMCDATA = require(LIBXML_REQUIRE_PATH..'dom.cdata')
4 |
5 | --
6 | -- Define class
7 | --
8 | local Text = upperclass:define("DOMText", DOMCDATA)
9 |
10 | --
11 | -- Returns true if the text node contains content whitespace, otherwise it returns false
12 | --
13 | property : isElementContentWhitespace {
14 | false;
15 | get='public';
16 | set='private';
17 | }
18 |
19 | --
20 | -- Returns all text of text nodes adjacent to this node, concatenated in document order
21 | --
22 | property : wholeText {
23 | nil;
24 | get='public';
25 | set='private';
26 | type='string';
27 | }
28 |
29 | --
30 | -- Class constructor
31 | --
32 | function private:__construct(TEXT)
33 | self:__constructparent(TEXT)
34 | self.nodeType = 3
35 | self.nodeName = "#text"
36 | end
37 |
38 | --
39 | -- Replaces the text of this node and all adjacent text nodes with the specified text
40 | --
41 | function public:replaceWholeText(TEXT)
42 | error("Method Not Yet Implimented")
43 | end
44 |
45 | --
46 | -- Compile class
47 | --
48 | return upperclass:compile(Text)
49 |
--------------------------------------------------------------------------------
/xml/dtd/dtdparser.lua:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rdlaitila/lua-libxml/126d1ea79089719506fa71cd886fa2275a237e21/xml/dtd/dtdparser.lua
--------------------------------------------------------------------------------
/xml/dtd/schemas/html_401_frameset.lua:
--------------------------------------------------------------------------------
1 | return [===[
2 |
21 |
26 |
27 |
28 | ...
29 |
30 |
33 |
34 | -->
35 |
36 |
37 |
38 | %HTML4.dtd;
39 | ]===]
--------------------------------------------------------------------------------
/xml/dtd/schemas/html_401_strict.lua:
--------------------------------------------------------------------------------
1 | return [===[
2 |
31 |
76 |
77 |
78 |
79 |
80 |
81 |
84 |
85 |
88 |
89 |
92 |
93 |
96 |
97 |
100 |
101 |
104 |
105 |
108 |
109 |
112 |
113 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
146 | %HTMLlat1;
147 |
148 |
151 | %HTMLsymbol;
152 |
153 |
156 | %HTMLspecial;
157 |
158 |
159 |
165 |
166 |
170 |
171 |
183 |
184 |
185 |
186 |
187 |
188 |
194 | ]]>
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
205 |
206 |
208 |
209 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
221 |
222 |
223 |
226 |
227 |
228 |
232 |
233 |
234 |
239 |
240 |
241 |
242 |
245 |
246 |
247 |
248 |
254 |
255 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
269 |
270 |
271 |
274 |
275 |
276 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
304 |
305 |
306 |
307 |
309 |
310 |
311 |
315 |
316 |
317 |
329 |
330 |
331 |
332 |
345 |
346 |
347 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
366 | ]]>
367 |
368 |
369 |
370 |
371 |
375 |
376 |
388 |
389 |
391 |
392 |
393 |
398 |
399 |
401 |
418 |
419 |
420 |
428 |
429 |
430 |
431 |
432 |
433 |
436 |
437 |
438 |
439 |
440 |
443 |
444 |
445 |
446 |
450 |
451 |
452 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
465 |
466 |
467 |
468 |
469 |
473 |
474 |
475 |
476 |
477 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
501 |
502 |
503 |
504 |
507 |
508 |
509 |
510 |
513 |
514 |
515 |
516 |
519 |
520 |
521 |
522 |
523 |
526 |
527 |
528 |
529 |
540 |
541 |
542 |
543 |
550 |
551 |
556 |
557 |
558 |
559 |
582 |
583 |
584 |
596 |
597 |
598 |
603 |
604 |
605 |
612 |
613 |
614 |
629 |
630 |
634 |
635 |
638 |
639 |
640 |
641 |
645 |
646 |
649 |
661 |
662 |
663 |
664 |
665 |
666 |
680 |
681 |
682 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
700 |
701 |
702 |
705 |
706 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
729 |
730 |
731 |
734 |
735 |
739 |
746 |
747 |
759 |
766 |
767 |
779 |
784 |
785 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
818 |
819 |
823 |
824 |
825 |
826 |
827 |
828 |
831 |
832 |
833 |
840 |
841 |
842 |
848 |
849 |
850 |
858 |
859 |
861 |
864 |
865 |
866 |
867 |
868 |
869 |
872 | ]===]
--------------------------------------------------------------------------------
/xml/dtd/schemas/xhtml_10_strict.lua:
--------------------------------------------------------------------------------
1 | return [===[
2 |
24 |
25 |
26 |
27 |
30 | %HTMLlat1;
31 |
32 |
35 | %HTMLsymbol;
36 |
37 |
40 | %HTMLspecial;
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
113 |
119 |
120 |
125 |
130 |
131 |
142 |
154 |
155 |
161 |
167 |
168 |
169 |
170 |
171 |
172 |
174 |
175 |
176 |
178 |
179 |
180 |
181 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
217 |
218 |
219 |
220 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
244 |
245 |
246 |
247 |
248 |
249 |
251 |
252 |
255 |
256 |
261 |
262 |
266 |
267 |
271 |
272 |
273 |
274 |
275 |
279 |
280 |
281 |
282 |
290 |
291 |
304 |
305 |
306 |
316 |
317 |
318 |
319 |
327 |
328 |
329 |
330 |
338 |
339 |
340 |
341 |
342 |
345 |
346 |
347 |
348 |
349 |
354 |
355 |
356 |
359 |
360 |
361 |
362 |
363 |
366 |
367 |
368 |
369 |
373 |
374 |
375 |
378 |
379 |
380 |
383 |
384 |
385 |
388 |
389 |
390 |
393 |
394 |
395 |
398 |
399 |
400 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
412 |
413 |
414 |
415 |
416 |
419 |
420 |
421 |
422 |
423 |
426 |
427 |
428 |
429 |
430 |
433 |
434 |
435 |
438 |
439 |
440 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
452 |
453 |
454 |
455 |
456 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
469 |
470 |
471 |
472 |
473 |
477 |
478 |
479 |
480 |
485 |
486 |
491 |
492 |
493 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
517 |
518 |
519 |
520 |
521 |
524 |
525 |
526 |
533 |
534 |
535 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
603 |
604 |
605 |
621 |
622 |
628 |
629 |
636 |
637 |
638 |
639 |
647 |
648 |
649 |
659 |
660 |
662 |
663 |
664 |
665 |
667 |
668 |
669 |
678 |
679 |
680 |
689 |
690 |
691 |
692 |
693 |
703 |
704 |
708 |
709 |
716 |
717 |
722 |
723 |
724 |
725 |
726 |
744 |
745 |
746 |
757 |
758 |
759 |
764 |
765 |
766 |
773 |
774 |
775 |
786 |
787 |
792 |
793 |
796 |
797 |
798 |
802 |
803 |
806 |
807 |
815 |
816 |
817 |
818 |
819 |
820 |
828 |
829 |
830 |
836 |
837 |
838 |
839 |
844 |
849 |
850 |
851 |
854 |
855 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
877 |
878 |
881 |
882 |
886 |
893 |
894 |
906 |
913 |
914 |
926 |
931 |
932 |
937 |
938 |
943 |
944 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
967 |
968 |
979 | ]===]
--------------------------------------------------------------------------------
/xml/dtd/schemas/xhtml_10_transitional.lua:
--------------------------------------------------------------------------------
1 | return [===[
2 |
24 |
25 |
26 |
27 |
30 | %HTMLlat1;
31 |
32 |
35 | %HTMLsymbol;
36 |
37 |
40 | %HTMLspecial;
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
125 |
126 |
127 |
128 |
134 |
140 |
141 |
146 |
151 |
152 |
163 |
175 |
176 |
182 |
188 |
189 |
190 |
191 |
193 |
194 |
195 |
196 |
197 |
198 |
200 |
201 |
203 |
204 |
206 |
207 |
208 |
209 |
211 |
212 |
213 |
214 |
215 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
251 |
252 |
254 |
255 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
280 |
281 |
282 |
283 |
284 |
285 |
287 |
288 |
291 |
292 |
297 |
298 |
302 |
303 |
307 |
308 |
309 |
310 |
311 |
316 |
317 |
318 |
319 |
327 |
328 |
341 |
342 |
343 |
354 |
355 |
356 |
357 |
365 |
366 |
367 |
368 |
377 |
378 |
379 |
380 |
381 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
403 |
404 |
405 |
406 |
407 |
410 |
411 |
412 |
413 |
414 |
425 |
426 |
427 |
431 |
432 |
433 |
434 |
435 |
439 |
440 |
441 |
442 |
446 |
447 |
448 |
452 |
453 |
454 |
458 |
459 |
460 |
464 |
465 |
466 |
470 |
471 |
472 |
476 |
477 |
478 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
497 |
498 |
509 |
510 |
511 |
512 |
513 |
514 |
520 |
521 |
522 |
523 |
527 |
528 |
529 |
530 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
546 |
547 |
548 |
549 |
550 |
554 |
555 |
556 |
559 |
560 |
561 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
573 |
574 |
575 |
576 |
577 |
584 |
585 |
586 |
587 |
589 |
590 |
591 |
596 |
597 |
598 |
599 |
600 |
604 |
605 |
606 |
607 |
608 |
609 |
612 |
613 |
614 |
615 |
620 |
621 |
626 |
627 |
628 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
653 |
654 |
655 |
656 |
657 |
660 |
661 |
662 |
669 |
670 |
671 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
749 |
750 |
751 |
758 |
759 |
760 |
766 |
767 |
768 |
788 |
789 |
795 |
796 |
803 |
804 |
805 |
809 |
810 |
824 |
825 |
826 |
827 |
833 |
834 |
835 |
850 |
851 |
853 |
854 |
855 |
856 |
858 |
859 |
860 |
869 |
870 |
871 |
881 |
882 |
883 |
884 |
885 |
886 |
898 |
899 |
903 |
904 |
911 |
912 |
917 |
918 |
919 |
920 |
921 |
940 |
941 |
942 |
953 |
954 |
955 |
960 |
961 |
962 |
969 |
970 |
971 |
982 |
983 |
988 |
989 |
992 |
993 |
994 |
995 |
996 |
1001 |
1002 |
1005 |
1006 |
1014 |
1015 |
1016 |
1017 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1035 |
1036 |
1037 |
1043 |
1044 |
1045 |
1046 |
1047 |
1048 |
1049 |
1054 |
1059 |
1060 |
1061 |
1064 |
1065 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 |
1076 |
1077 |
1089 |
1090 |
1091 |
1092 |
1096 |
1097 |
1101 |
1108 |
1109 |
1121 |
1128 |
1129 |
1141 |
1146 |
1147 |
1152 |
1153 |
1158 |
1159 |
1165 |
1166 |
1167 |
1168 |
1169 |
1170 |
1171 |
1186 |
1187 |
1202 | ]===]
--------------------------------------------------------------------------------
/xml/dtd/schemas/xhtml_11.lua:
--------------------------------------------------------------------------------
1 | return [===[
2 |
3 |
4 |
6 |
7 |
29 |
35 |
36 |
37 |
50 |
51 |
52 |
53 |
56 |
57 |
58 |
60 |
61 |
62 |
63 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
99 |
100 | ]]>
103 |
104 |
105 |
106 |
107 |
108 |
112 | %xhtml-inlstyle.mod;]]>
113 |
114 |
116 |
119 |
120 |
121 |
122 |
123 |
127 | %xhtml-datatypes.mod;]]>
128 |
129 |
133 |
134 |
135 |
136 |
140 | %xhtml-framework.mod;]]>
141 |
142 |
143 |
146 |
147 | ]]>
150 |
151 |
152 |
153 |
157 | %xhtml-text.mod;]]>
158 |
159 |
160 |
161 |
165 | %xhtml-hypertext.mod;]]>
166 |
167 |
168 |
169 |
173 | %xhtml-list.mod;]]>
174 |
175 |
176 |
177 |
178 |
179 |
183 | %xhtml-edit.mod;]]>
184 |
185 |
186 |
187 |
191 | %xhtml-bdo.mod;]]>
192 |
193 |
194 |
195 |
196 |
197 |
201 | %xhtml-ruby.mod;]]>
202 |
203 |
204 |
205 |
209 | %xhtml-pres.mod;]]>
210 |
211 |
212 |
213 |
217 | %xhtml-link.mod;]]>
218 |
219 |
220 |
221 |
225 | %xhtml-meta.mod;]]>
226 |
227 |
228 |
229 |
233 | %xhtml-base.mod;]]>
234 |
235 |
236 |
237 |
241 | %xhtml-script.mod;]]>
242 |
243 |
244 |
245 |
249 | %xhtml-style.mod;]]>
250 |
251 |
252 |
253 |
257 | %xhtml-image.mod;]]>
258 |
259 |
260 |
261 |
265 | %xhtml-csismap.mod;]]>
266 |
267 |
268 |
269 |
273 | %xhtml-ssismap.mod;]]>
274 |
275 |
276 |
277 |
281 | %xhtml-param.mod;]]>
282 |
283 |
284 |
285 |
289 | %xhtml-object.mod;]]>
290 |
291 |
292 |
293 |
297 | %xhtml-table.mod;]]>
298 |
299 |
300 |
301 |
305 | %xhtml-form.mod;]]>
306 |
307 |
308 |
309 |
313 | %xhtml-legacy.mod;]]>
314 |
315 |
316 |
317 |
321 | %xhtml-struct.mod;]]>
322 |
323 |
324 |
325 | ]===]
--------------------------------------------------------------------------------
/xml/init.lua:
--------------------------------------------------------------------------------
1 | --
2 | -- Obtain our require path. This should the the folder of the loader.lua file
3 | --
4 | LIBXML_REQUIRE_PATH = (...):match("(.-)[^%.]+$")
5 |
6 | return {
7 | -- Our version: Major.Minor.Patch
8 | version = "0.1.0";
9 |
10 | -- Our DOM Objects
11 | dom = {
12 | Attribute = require(LIBXML_REQUIRE_PATH..'dom.attribute'),
13 | CDATA = require(LIBXML_REQUIRE_PATH..'dom.cdata'),
14 | Comment = require(LIBXML_REQUIRE_PATH..'dom.comment'),
15 | Document = require(LIBXML_REQUIRE_PATH..'dom.document'),
16 | DocumentImplimentation = require(LIBXML_REQUIRE_PATH..'dom.documentimplimentation'),
17 | DocumentType = require(LIBXML_REQUIRE_PATH..'dom.documenttype'),
18 | DOMParser = require(LIBXML_REQUIRE_PATH..'dom.domparser'),
19 | Element = require(LIBXML_REQUIRE_PATH..'dom.element'),
20 | NamedNodeMap = require(LIBXML_REQUIRE_PATH..'dom.namednodemap'),
21 | Node = require(LIBXML_REQUIRE_PATH..'dom.node'),
22 | NodeList = require(LIBXML_REQUIRE_PATH..'dom.nodelist'),
23 | ProcessingInstruction = require(LIBXML_REQUIRE_PATH..'dom.processinginstruction'),
24 | Text = require(LIBXML_REQUIRE_PATH..'dom.text'),
25 | };
26 |
27 | -- Our DTD Objects
28 | dtd = {
29 | DTDParser = require(LIBXML_REQUIRE_PATH..'dtd.dtdparser'),
30 | schemas = {
31 | {name = "-//W3C//DTD HTML 4.01//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.html_401_strict')},
32 | {name = "-//W3C//DTD HTML 4.01 Transitional//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.html_401_transitional')},
33 | {name = "-//W3C//DTD HTML 4.01 Frameset//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.html_401_frameset')},
34 | {name = "-//W3C//DTD XHTML 1.0 Strict//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.xhtml_10_strict')},
35 | {name = "-//W3C//DTD XHTML 1.0 Transitional//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.xhtml_10_transitional')},
36 | {name = "-//W3C//DTD XHTML 1.0 Frameset//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.xhtml_10_frameset')},
37 | {name = "-//W3C//DTD XHTML 1.1//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.xhtml_11')},
38 | {name = "-//W3C//DTD MathML 2.0//EN", text = require(LIBXML_REQUIRE_PATH..'dtd.schemas.mathml_20')},
39 | }
40 | };
41 |
42 | -- Our Library Objects
43 | lib = {
44 | upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass'),
45 | utils = require(LIBXML_REQUIRE_PATH..'lib.utils')
46 | };
47 | }
--------------------------------------------------------------------------------
/xml/lib/upperclass.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2014 Regan Daniel Laitila
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | ]]
24 |
25 | local upperclass = {}
26 |
27 | -- Our version: Major.Minor.Patch
28 | upperclass.version = "0.2.2"
29 |
30 | --
31 | -- Define some static scope properties for use internally, respect existing global
32 | --
33 | if UPPERCLASS_SCOPE_PRIVATE == nil then UPPERCLASS_SCOPE_PRIVATE = {} end
34 | if UPPERCLASS_SCOPE_PROTECTED == nil then UPPERCLASS_SCOPE_PROTECTED = {} end
35 | if UPPERCLASS_SCOPE_PUBLIC == nil then UPPERCLASS_SCOPE_PUBLIC = {} end
36 | if UPPERCLASS_SCOPE_NOBODY == nil then UPPERCLASS_SCOPE_NOBODY = {} end
37 |
38 | --
39 | -- Define some member type properties for use internally, respect existing global
40 | --
41 | if UPPERCLASS_MEMBER_TYPE_PROPERTY == nil then UPPERCLASS_MEMBER_TYPE_PROPERTY = {} end
42 | if UPPERCLASS_MEMBER_TYPE_FUNCTION == nil then UPPERCLASS_MEMBER_TYPE_FUNCTION = {} end
43 |
44 | --
45 | -- Define some types, respect existing global
46 | --
47 | if UPPERCLASS_TYPE_ANY == nil then UPPERCLASS_TYPE_ANY = {string='any'} end
48 | if UPPERCLASS_TYPE_STRING == nil then UPPERCLASS_TYPE_STRING = {string='string'} end
49 | if UPPERCLASS_TYPE_TABLE == nil then UPPERCLASS_TYPE_TABLE = {string='table'} end
50 | if UPPERCLASS_TYPE_FUNCTION == nil then UPPERCLASS_TYPE_FUNCTION = {string='function'} end
51 | if UPPERCLASS_TYPE_NUMBER == nil then UPPERCLASS_TYPE_NUMBER = {string='number'} end
52 | if UPPERCLASS_TYPE_USERDATA == nil then UPPERCLASS_TYPE_USERDATA = {string='userdata'} end
53 | if UPPERCLASS_TYPE_NIL == nil then UPPERCLASS_TYPE_NIL = {string='nil'} end
54 | if UPPERCLASS_TYPE_BOOLEAN == nil then UPPERCLASS_TYPE_BOOLEAN = {string='boolean'} end
55 |
56 | --
57 | -- Global to indicate during metamethod calls that we wish to continue with default lookup behaviors, respect existing global
58 | --
59 | if UPPERCLASS_DEFAULT_BEHAVIOR == nil then UPPERCLASS_DEFAULT_BEHAVIOR = {} end
60 |
61 | --
62 | -- Holds the metatable used during the class definition stage
63 | --
64 | local ClassDefinitionMetatable = {classDefinitionTable = nil}
65 |
66 | --
67 | -- Holds the metatable used during class runtime operations
68 | --
69 | local ClassRuntimeMetatable = {}
70 |
71 | --
72 | -- Dumps class members
73 | --
74 | function upperclass:dumpClassMembers(CLASS, SORT_COLUMN)
75 | -- Some spacing
76 | print(" ")
77 | print("-= MEMBER DUMP START =- ")
78 |
79 | -- Sets which colum of output to sort
80 | if SORT_COLUMN == nil then SORT_COLUMN = 1 end
81 |
82 | -- Function to generate a string of specified length
83 | local genstring = function(LEN)
84 | local str = ""
85 | for a=1, LEN do
86 | str = str .. " "
87 | end
88 | return str
89 | end
90 |
91 | -- Holds our table of class members
92 | local dumpTable = {}
93 |
94 | -- Walk the class and its parents obtaining members
95 | local targetClass = CLASS
96 | while targetClass ~= nil do
97 | for key, value in pairs(targetClass.__imp__.members) do
98 | table.insert(dumpTable, {
99 | tostring(key),
100 | targetClass.__imp__.members[key].member_scope_get,
101 | targetClass.__imp__.members[key].member_scope_set,
102 | targetClass.__imp__.members[key].member_type,
103 | targetClass.__imp__.members[key].value_type,
104 | tostring(targetClass.__imp__.members[key].value_default),
105 | tostring(upperclass:getClassMemberValue(targetClass, key)),
106 | tostring(targetClass.__imp__.name),
107 | })
108 | end
109 |
110 | if targetClass.__parent__ ~= nil then
111 | targetClass = targetClass.__parent__
112 | else
113 | targetClass = nil
114 | end
115 | end
116 |
117 | -- Replace values in dumptable with friendly names
118 | for a=1, #dumpTable do
119 | for b=1, #dumpTable[a] do
120 | if dumpTable[a][b] == UPPERCLASS_MEMBER_TYPE_FUNCTION then
121 | dumpTable[a][b] = "method"
122 | elseif dumpTable[a][b] == UPPERCLASS_MEMBER_TYPE_PROPERTY then
123 | dumpTable[a][b] = "property"
124 | elseif dumpTable[a][b] == UPPERCLASS_SCOPE_PUBLIC then
125 | dumpTable[a][b] = "public"
126 | elseif dumpTable[a][b] == UPPERCLASS_SCOPE_PRIVATE then
127 | dumpTable[a][b] = "private"
128 | elseif dumpTable[a][b] == UPPERCLASS_SCOPE_PROTECTED then
129 | dumpTable[a][b] = "protected"
130 | elseif dumpTable[a][b] == UPPERCLASS_SCOPE_NOBODY then
131 | dumpTable[a][b] = "nobody"
132 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_STRING then
133 | dumpTable[a][b] = "string"
134 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_NUMBER then
135 | dumpTable[a][b] = "number"
136 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_TABLE then
137 | dumpTable[a][b] = "table"
138 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_BOOLEAN then
139 | dumpTable[a][b] = "boolean"
140 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_FUNCTION then
141 | dumpTable[a][b] = "function"
142 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_NIL then
143 | dumpTable[a][b] = "nil"
144 | elseif dumpTable[a][b] == UPPERCLASS_TYPE_ANY then
145 | dumpTable[a][b] = "any"
146 | end
147 | end
148 | end
149 |
150 | -- Determine the longest key for each column
151 | local dumpTableColumnSpacing = {0, 0, 0, 0, 0, 0, 0, 0}
152 |
153 | -- Our header row
154 | local header = {"MEMBER_NAME", "MEMBER_SCOPE_GET", "MEMBER_SCOPE_SET", "MEMBER_TYPE", "MEMBER_VALUE_TYPE", "MEMBER_VALUE_DEFAULT", "MEMBER_VALUE_CURRENT", "MEMBER_CLASS_IMPL"}
155 | for a=1, #header do
156 | if header[a]:len() > dumpTableColumnSpacing[a] then
157 | dumpTableColumnSpacing[a] = header[a]:len()
158 | end
159 | end
160 |
161 | -- Set the longest key value per column
162 | for a=1, #dumpTable do
163 | for b=1, #dumpTable[a] do
164 | if tostring(dumpTable[a][b]):len() > dumpTableColumnSpacing[b] then
165 | dumpTableColumnSpacing[b] = tostring(dumpTable[a][b]):len() or 0
166 | end
167 | end
168 | end
169 |
170 | -- Update the dumpTable values with appropriate spacing
171 | local dumpTableSpaced = {}
172 | for a=1, #dumpTable do
173 | for b=1, #dumpTable[a] do
174 | dumpTable[a][b] = tostring(dumpTable[a][b]) .. genstring(dumpTableColumnSpacing[b] + 2 - tostring(dumpTable[a][b]):len())
175 | end
176 | end
177 |
178 | -- Update the header values with appropriate spacing
179 | for a=1, #header do
180 | header[a] = header[a] .. genstring(dumpTableColumnSpacing[a] + 2 - header[a]:len())
181 | end
182 | print(unpack(header))
183 |
184 | -- Sort our table
185 | table.sort(dumpTable, function(A, B)
186 | return A[SORT_COLUMN] < B[SORT_COLUMN]
187 | end)
188 |
189 | -- Print our dump table
190 | for a=1, #dumpTable do
191 | print(unpack(dumpTable[a]))
192 | end
193 |
194 | -- Print additional spacing
195 | print("-= MEMBER DUMP END =- ")
196 | print(" ")
197 | end
198 |
199 | --
200 | -- Returns a class member
201 | --
202 | function upperclass:getClassMember(CLASS, KEY)
203 | if rawget(CLASS, '__imp__').members[KEY] ~= nil then
204 | return rawget(CLASS, '__imp__').members[KEY]
205 | elseif rawget(CLASS, '__parent__') ~= nil then
206 | return upperclass:getClassMember(rawget(CLASS, '__parent__'), KEY)
207 | end
208 | end
209 |
210 | --
211 | -- Returns all class members, searching through all parents
212 | --
213 | function upperclass:getClassMembers(CLASS, RECURSE)
214 | local targetClass = CLASS
215 | local members = {}
216 |
217 | if RECURSE == nil then
218 | RECURSE = false
219 | end
220 |
221 | while targetClass ~= nil do
222 | for key, value in pairs(targetClass.__imp__.members) do
223 | table.insert(members, targetClass.__imp__.members[key])
224 | end
225 |
226 | if RECURSE == true then
227 | if targetClass.__parent__ ~= nil then
228 | targetClass = targetClass.__parent__
229 | else
230 | targetClass = nil
231 | end
232 | else
233 | targetClass = nil
234 | end
235 | end
236 |
237 | return members
238 | end
239 |
240 | --
241 | -- Atempts to obtain a class member value
242 | --
243 | function upperclass:getClassMemberValue(CLASS, KEY)
244 | if rawget(CLASS, '__inst__').memberValueOverrides[KEY] ~= nil then
245 | return rawget(CLASS, '__inst__').memberValueOverrides[KEY].value
246 | elseif rawget(CLASS, '__imp__').members[KEY] ~= nil then
247 | return rawget(CLASS, '__imp__').members[KEY].value_default
248 | elseif rawget(CLASS, '__parent__') ~= nil then
249 | return upperclass:getClassMemberValue(rawget(CLASS, '__parent__'), KEY)
250 | end
251 | end
252 |
253 | --
254 | -- Upperclass Define function.
255 | --
256 | function upperclass:define(CLASS_NAME, PARENT)
257 | local classdef = {}
258 |
259 | -- Gracefully take over globals: public, private, protected, property
260 | -- we will set them back to orig values after definition
261 | classdef.public_orig_value = rawget(_G, "public")
262 | classdef.private_orig_value = rawget(_G, "private")
263 | classdef.protected_orig_value = rawget(_G, "protected")
264 | classdef.property_orig_value = rawget(_G, "property")
265 |
266 | -- Create class implimentation table
267 | classdef.__imp__ = {
268 | name = tostring(CLASS_NAME),
269 | members = {}
270 | }
271 |
272 | -- Store the class file
273 | if debug ~= nil then
274 | classdef.__imp__.file = debug.getinfo(2, "S").source:sub(2)
275 | else
276 | classdef.__imp__.file = nil
277 | end
278 |
279 | -- Create tables to hold instance values
280 | classdef.__inst__ = {
281 | isClassInstance = false,
282 | memberValueOverrides = {},
283 | permitMetamethodCalls = true
284 | }
285 |
286 | -- Create table to hold reference to our parent class, if specified
287 | classdef.__parent__ = PARENT or nil
288 |
289 | -- During the definition stage, the user may place property and method definitions in the following tables
290 | rawset(_G, "public", {})
291 | rawset(_G, "private", {})
292 | rawset(_G, "protected", {})
293 | rawset(_G, "property", {})
294 |
295 | -- Set our metatables.
296 | setmetatable(classdef, ClassDefinitionMetatable)
297 | setmetatable(public, ClassDefinitionMetatable)
298 | setmetatable(private, ClassDefinitionMetatable)
299 | setmetatable(protected, ClassDefinitionMetatable)
300 | setmetatable(property, ClassDefinitionMetatable)
301 |
302 | -- The ClassDefinitionMetatable will need a reference to the ClassDefinitionTable
303 | ClassDefinitionMetatable.classDefinitionTable = classdef
304 |
305 | return classdef
306 | end
307 |
308 | --
309 | -- Upperclass Compile Function
310 | --
311 | function upperclass:compile(CLASS)
312 | -- Return our stolen globals to original state
313 | rawset(_G, "public", CLASS.public_orig_value)
314 | rawset(_G, "private", CLASS.private_orig_value)
315 | rawset(_G, "protected", CLASS.protected_orig_value)
316 | rawset(_G, "property", CLASS.property_orig_value)
317 |
318 | setmetatable(CLASS, nil)
319 |
320 | -- If __construct was not defined, define it now
321 | if CLASS.__imp__.members["__construct"] == nil then
322 | CLASS.__imp__.members["__construct"] = {
323 | member_scope_get = UPPERCLASS_SCOPE_PRIVATE,
324 | member_scope_set = UPPERCLASS_SCOPE_NOBODY,
325 | member_type = UPPERCLASS_MEMBER_TYPE_FUNCTION,
326 | value_type = UPPERCLASS_TYPE_FUNCTION,
327 | value_default = function() end,
328 | }
329 | end
330 |
331 | -- Define __constructparent() method
332 | CLASS.__imp__.members["__constructparent"] = {
333 | member_scope_get = UPPERCLASS_SCOPE_PRIVATE,
334 | member_scope_set = UPPERCLASS_SCOPE_NOBODY,
335 | member_type = UPPERCLASS_MEMBER_TYPE_FUNCTION,
336 | value_type = UPPERCLASS_TYPE_FUNCTION,
337 | value_default = function(self, ...)
338 | local constructArgs = {...}
339 | if self.__parent__.__inst__.isClassInstance == false then
340 | self.__parent__ = self.__parent__(unpack(constructArgs))
341 | end
342 | end,
343 | }
344 |
345 | -- Set the class's metatable to ClassRuntimeMetatable
346 | setmetatable(CLASS, ClassRuntimeMetatable)
347 |
348 | return CLASS
349 | end
350 |
351 | --
352 | -- ClassDefinitionMetatable __call method
353 | --
354 | function ClassDefinitionMetatable.__call(...)
355 | local tables = {...}
356 |
357 | -- Get our implimentation table
358 | local imp = rawget(ClassDefinitionMetatable.classDefinitionTable, "__imp__")
359 |
360 | -- Get our implimentation members table
361 | local members = rawget(imp, "members")
362 |
363 | -- Get our property definition values
364 | local propertyTable = tables[3]
365 | local propertyGetterValue = propertyTable.get
366 | local propertySetterValue = propertyTable.set
367 | local propertyTypeValue = propertyTable.type
368 | local propertyDefaultValue = propertyTable[1]
369 |
370 | -- If property table length is 0, then set member values to defaults
371 | local proptablelen = 0
372 | for key, value in pairs(propertyTable) do proptablelen = proptablelen +1 end
373 | if proptablelen == 0 then
374 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_PUBLIC
375 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_PUBLIC
376 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_ANY
377 | members[ClassDefinitionMetatable.last_property_name].value_default = nil
378 | else
379 | -- Determine value type & value
380 | if propertyTypeValue == 'any' then
381 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_ANY
382 | members[ClassDefinitionMetatable.last_property_name].value_default = propertyDefaultValue
383 | elseif propertyTypeValue == nil and propertyDefaultValue ~= nil then
384 | if type(propertyDefaultValue) == "string" then
385 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_STRING
386 | elseif type(propertyDefaultValue) == "table" then
387 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_TABLE
388 | elseif type(propertyDefaultValue) == "number" then
389 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_NUMBER
390 | elseif type(propertyDefaultValue) == "userdata" then
391 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_USERDATA
392 | elseif type(propertyDefaultValue) == "boolean" then
393 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_BOOLEAN
394 | elseif type(propertyDefaultValue) == nil then
395 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_ANY
396 | end
397 | members[ClassDefinitionMetatable.last_property_name].value_default = propertyDefaultValue
398 | elseif propertyTypeValue ~= nil and propertyDefaultValue == nil then
399 | if propertyTypeValue == 'string' then
400 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_STRING
401 | elseif propertyTypeValue == 'table' then
402 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_TABLE
403 | elseif propertyTypeValue == 'number' then
404 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_NUMBER
405 | elseif propertyTypeValue == 'userdata' then
406 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_USERDATA
407 | elseif propertyTypeValue == 'boolean' then
408 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_BOOLEAN
409 | end
410 | members[ClassDefinitionMetatable.last_property_name].value_default = nil
411 | elseif propertyTypeValue ~= nil and propertyDefaultValue ~= nil and propertyTypeValue == type(propertyDefaultValue) then
412 | if type(propertyDefaultValue) == "string" then
413 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_STRING
414 | elseif type(propertyDefaultValue) == "table" then
415 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_TABLE
416 | elseif type(propertyDefaultValue) == "number" then
417 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_NUMBER
418 | elseif type(propertyDefaultValue) == "userdata" then
419 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_USERDATA
420 | elseif type(propertyDefaultValue) == "boolean" then
421 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_BOOLEAN
422 | elseif type(propertyDefaultValue) == nil then
423 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_ANY
424 | end
425 | members[ClassDefinitionMetatable.last_property_name].value_default = propertyDefaultValue
426 | elseif propertyTypeValue == nil and propertyDefaultValue == nil then
427 | members[ClassDefinitionMetatable.last_property_name].value_type = UPPERCLASS_TYPE_ANY
428 | members[ClassDefinitionMetatable.last_property_name].value_default = propertyDefaultValue
429 | elseif propertyTypeValue == 'function' or type(propertyDefaultValue) == 'function' then
430 | error("Attempt to define class member property of type 'function' is disallowed. Please define a class member function instead.")
431 | else
432 | error("Attempt to define class member property '"..ClassDefinitionMetatable.last_property_name.."' as type '"..tostring(propertyTypeValue).."' when supplied value is of type '"..tostring(type(propertyDefaultValue)).."' is disallowed")
433 | end
434 |
435 | -- Determine getter scope
436 | if propertyGetterValue == 'public' then
437 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_PUBLIC
438 | elseif propertyGetterValue == 'private' then
439 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_PRIVATE
440 | elseif propertyGetterValue == 'protected' then
441 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_PROTECTED
442 | elseif propertyGetterValue == 'nobody' then
443 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_NOBODY
444 | else
445 | members[ClassDefinitionMetatable.last_property_name].member_scope_get = UPPERCLASS_SCOPE_PUBLIC
446 | end
447 |
448 | -- Determine setter scope
449 | if propertySetterValue == 'public' then
450 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_PUBLIC
451 | elseif propertySetterValue == 'private' then
452 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_PRIVATE
453 | elseif propertySetterValue == 'protected' then
454 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_PROTECTED
455 | elseif propertySetterValue == 'nobody' then
456 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_NOBODY
457 | else
458 | members[ClassDefinitionMetatable.last_property_name].member_scope_set = UPPERCLASS_SCOPE_PUBLIC
459 | end
460 | end
461 | end
462 |
463 | --
464 | -- ClassDefinitionMetatable __index method
465 | --
466 | function ClassDefinitionMetatable.__index(TABLE, KEY)
467 | -- Check what kind of index we are retreiving. If requesting table is 'property'
468 | -- we must create a skeleton member entry with the requested key for later use
469 | -- in the __call metamethod.
470 | if TABLE == property then
471 | -- Get our implimentation table
472 | local imp = rawget(ClassDefinitionMetatable.classDefinitionTable, "__imp__")
473 |
474 | -- Get our implimentation members table
475 | local members = rawget(imp, "members")
476 |
477 | -- Ensure we are not redefining an existing member
478 | if members[KEY] ~= nil then
479 | error("Attempt to redefine existing member '"..KEY.."' in class '"..imp.name.."' is disallowed")
480 | end
481 |
482 | -- Setup our member property table with defaults that will be later thrown away
483 | -- in the __call metamethod
484 | members[KEY] = {
485 | member_scope_get = UPPERCLASS_SCOPE_NOBODY,
486 | member_scope_set = UPPERCLASS_SCOPE_NOBODY,
487 | member_type = UPPERCLASS_MEMBER_TYPE_PROPERTY,
488 | value_type = UPPERCLASS_TYPE_NIL,
489 | value_default = nil,
490 | }
491 |
492 | -- Set the last property name being defined for use in the __call metamethod
493 | ClassDefinitionMetatable.last_property_name = KEY
494 |
495 | return property
496 | else
497 | return rawget(TABLE, KEY)
498 | end
499 | end
500 |
501 | --
502 | -- ClassDefinitionMetatable __newindex
503 | --
504 | function ClassDefinitionMetatable.__newindex(TABLE, KEY, VALUE)
505 | -- Get our implimentation table
506 | local imp = rawget(ClassDefinitionMetatable.classDefinitionTable, "__imp__")
507 |
508 | -- Get our implimentation members table
509 | local members = rawget(imp, "members")
510 |
511 | -- Ensure we are not redefining an existing member
512 | if members[KEY] ~= nil then
513 | error("Attempt to redefine existing member '"..KEY.."' in class '"..imp.name.."' is disallowed")
514 | end
515 |
516 | -- Create our members based on type and scope
517 | members[KEY] = {
518 | member_scope_get = UPPERCLASS_SCOPE_NOBODY,
519 | member_scope_set = UPPERCLASS_SCOPE_NOBODY,
520 | member_type = (function()
521 | if type(VALUE) == "function" then
522 | return UPPERCLASS_MEMBER_TYPE_FUNCTION
523 | else
524 | return UPPERCLASS_MEMBER_TYPE_PROPERTY
525 | end
526 | end)(),
527 | value_type = (function()
528 | if type(VALUE) == "string" then
529 | return UPPERCLASS_TYPE_STRING
530 | elseif type(VALUE) == "table" then
531 | return UPPERCLASS_TYPE_TABLE
532 | elseif type(VALUE) == "function" then
533 | return UPPERCLASS_TYPE_FUNCTION
534 | elseif type(VALUE) == "number" then
535 | return UPPERCLASS_TYPE_NUMBER
536 | elseif type(VALUE) == "userdata" then
537 | return UPPERCLASS_TYPE_USERDATA
538 | elseif type(VALUE) == "boolean" then
539 | return UPPERCLASS_TYPE_BOOLEAN
540 | elseif VALUE == nil then
541 | return UPPERCLASS_TYPE_ANY
542 | end
543 | end)(),
544 | value_default = VALUE
545 | }
546 | if TABLE == rawget(_G, "public") then
547 | members[KEY].member_scope_get = UPPERCLASS_SCOPE_PUBLIC
548 | members[KEY].member_scope_set = UPPERCLASS_SCOPE_PUBLIC
549 | elseif TABLE == rawget(_G, "private") then
550 | members[KEY].member_scope_get = UPPERCLASS_SCOPE_PRIVATE
551 | members[KEY].member_scope_set = UPPERCLASS_SCOPE_PRIVATE
552 | elseif TABLE == rawget(_G, "protected") then
553 | members[KEY].member_scope_get = UPPERCLASS_SCOPE_PROTECTED
554 | members[KEY].member_scope_set = UPPERCLASS_SCOPE_PROTECTED
555 | end
556 |
557 | -- If we are defining a function, set setter scope to nobody as you cannot redefine functions at runtime
558 | if type(VALUE) == "function" then
559 | members[KEY].member_scope_set = UPPERCLASS_SCOPE_NOBODY
560 | end
561 | end
562 |
563 | --
564 | -- ClassRuntimeMetatable __call method
565 | --
566 | function ClassRuntimeMetatable.__call(...)
567 | -- Pack args
568 | local arguments = {...}
569 |
570 | -- Get table argument, a.k.a 'self'
571 | local self = arguments[1]
572 |
573 | -- Define instance table to return
574 | local instance = {}
575 |
576 | -- Setup reference to class implimentation
577 | instance.__imp__ = self.__imp__
578 |
579 | -- Setup table to hold instance implimentation
580 | instance.__inst__ = {
581 | isClassInstance = true,
582 | memberValueOverrides = {},
583 | permitMetamethodCalls = true
584 | }
585 |
586 | -- Set parent reference
587 | instance.__parent__ = self.__parent__
588 |
589 | setmetatable(instance, ClassRuntimeMetatable)
590 |
591 | -- Call class constructor
592 | local passargs = {}
593 | if #arguments > 1 then for a=2, #arguments do table.insert(passargs, arguments[a]) end end
594 | local __construct = self.__imp__.members["__construct"].value_default
595 | __construct(instance, unpack(passargs))
596 |
597 | -- Construct parent
598 | if instance.__parent__ ~= nil and instance.__parent__.__inst__.isClassInstance == false then
599 | instance.__parent__ = self.__parent__()
600 | end
601 |
602 | return instance
603 | end
604 |
605 | --
606 | -- ClassRuntimeMetatable __index method
607 | --
608 | function ClassRuntimeMetatable.__index(TABLE, KEY)
609 | -- Ensure we return some important keys.
610 | if KEY == "__imp__" or KEY == "__inst__" or KEY == "__parent__" then
611 | return rawget(TABLE, KEY)
612 | end
613 |
614 | local classimp = rawget(TABLE, '__imp__')
615 | local classinst = rawget(TABLE, '__inst__')
616 |
617 | -- Attempt to locate a user defined __index member and call it
618 | if KEY ~= '__index' and upperclass:getClassMember(TABLE, '__index') ~= nil and classinst.permitMetamethodCalls == true then
619 | -- We must set permitMetamethodCalls to false to stop recursive behavior
620 | classinst.permitMetamethodCalls = false
621 |
622 | -- Call the __index user defined member
623 | local indexMetamethodMemberRetVal = upperclass:getClassMember(TABLE, '__index').value_default(TABLE, KEY)
624 |
625 | -- Reenable permitMetamethodCalls
626 | classinst.permitMetamethodCalls = true
627 |
628 | if indexMetamethodMemberRetVal ~= UPPERCLASS_DEFAULT_BEHAVIOR then
629 | return indexMetamethodMemberRetVal
630 | end
631 | end
632 |
633 | -- get our target member
634 | local targetMember = upperclass:getClassMember(TABLE, KEY)
635 |
636 |
637 | -- Halt if our target member is nil
638 | if targetMember == nil then
639 | error("Attempt to obtain non-existant class member '"..tostring(KEY).."' in class '"..tostring(classimp.name).."' is disallowed")
640 | end
641 |
642 | --[[
643 | ANY LOGIC PAST THIS POINT ASSUMES A VALID MEMBER LOOKUP
644 | --]]
645 |
646 | -- Return members based on scope
647 | if targetMember.member_scope_get == UPPERCLASS_SCOPE_PUBLIC or debug == nil then
648 | return upperclass:getClassMemberValue(TABLE, KEY)
649 | elseif targetMember.member_scope_get == UPPERCLASS_SCOPE_PRIVATE then
650 | local caller = debug.getinfo(2, 'f').func
651 | local members = upperclass:getClassMembers(TABLE, false)
652 | for a=1, #members do
653 | if caller == members[a].value_default then
654 | --return TABLE.__inst__.memberValueOverrides[KEY] or targetMember.value_default
655 | return upperclass:getClassMemberValue(TABLE, KEY)
656 | end
657 | end
658 | error("Attempt to retrieve private member '"..tostring(KEY).."' from outside of class '"..TABLE.__imp__.name.."' is disallowed")
659 | elseif targetMember.member_scope_get == UPPERCLASS_SCOPE_PROTECTED then
660 | local caller = debug.getinfo(2, 'f').func
661 | local members = upperclass:getClassMembers(TABLE, true)
662 | for a=1, #members do
663 | if caller == members[a].value_default then
664 | --return TABLE.__inst__.memberValueOverrides[KEY] or targetMember.value_default
665 | return upperclass:getClassMemberValue(TABLE, KEY)
666 | end
667 | end
668 | error("Attempt to retrieve protected member '"..tostring(KEY).."' from outside of class '"..TABLE.__imp__.name.."' is disallowed")
669 | end
670 | end
671 |
672 | --
673 | -- ClassRuntimeMetatable __newindex method
674 | --
675 | function ClassRuntimeMetatable.__newindex(TABLE, KEY, VALUE)
676 | -- Ensure we return some important keys.
677 | if KEY == "__imp__" or KEY == "__inst__" or KEY == "__parent__" then
678 | error("Attempt to set internal class member '"..tostring(KEY).."' is disallowed")
679 | end
680 |
681 | local classimp = rawget(TABLE, '__imp__')
682 | local classinst = rawget(TABLE, '__inst__')
683 |
684 | -- Attempt to locate a user defined __newindex member and call it
685 | if KEY ~= '__newindex' and upperclass:getClassMember(TABLE, '__newindex') ~= nil and classinst.permitMetamethodCalls == true then
686 | -- We must set permitMetamethodCalls to false to stop recursive behavior
687 | classinst.permitMetamethodCalls = false
688 |
689 | -- Call the __index user defined member
690 | local newindexMetamethodMemberRetVal = upperclass:getClassMember(TABLE, '__newindex').value_default(TABLE, KEY, VALUE)
691 |
692 | -- Reenable permitMetamethodCalls
693 | classinst.permitMetamethodCalls = true
694 |
695 | if newindexMetamethodMemberRetVal ~= UPPERCLASS_DEFAULT_BEHAVIOR then
696 | return newindexMetamethodMemberRetVal
697 | end
698 | end
699 |
700 | -- Attempt to locate a target member
701 | local targetMember = upperclass:getClassMember(TABLE, KEY)
702 |
703 | -- Halt if our target member is nil
704 | if targetMember == nil then
705 | error("Attempt to obtain non-existant class member '"..tostring(KEY).."' in class '"..tostring(TABLE.__imp__.name).."' is disallowed")
706 | end
707 |
708 | -- Halt if our target member is a method
709 | if targetMember.member_type == UPPSERCLASS_MEMBER_TYPE_FUNCTION then
710 | error("Attempt to override member method '"..tostring(KEY).."' is disallowed")
711 | end
712 |
713 | --[[
714 | ANY LOGIC PAST THIS POINT ASSUMES A VALID MEMBER LOOKUP
715 | --]]
716 |
717 | -- Holds a boolean determining if our scope is proper
718 | local scopePermitted = false
719 |
720 | -- Holds a boolean determining if edit is allowed
721 | local editPermitted = false
722 |
723 | -- Conduct scope check
724 | if debug == nil or targetMember.member_scope_set == UPPERCLASS_SCOPE_PUBLIC then
725 | scopePermitted = true
726 | elseif targetMember.member_scope_set == UPPERCLASS_SCOPE_PRIVATE then
727 | local caller = debug.getinfo(2, 'f').func
728 | local members = upperclass:getClassMembers(TABLE, false)
729 | for a=1, #members do
730 | if caller == members[a].value_default then
731 | scopePermitted = true
732 | end
733 | end
734 | if scopePermitted ~= true then
735 | error("Attempt to set private member '"..tostring(KEY).."' from outside class '"..TABLE.__imp__.name.."' is disallowed")
736 | end
737 | elseif targetMember.member_scope_set == UPPERCLASS_SCOPE_PROTECTED then
738 | local caller = debug.getinfo(2, 'f').func
739 | local members = upperclass:getClassMembers(TABLE, true)
740 | for a=1, #members do
741 | if caller == members[a].value_default then
742 | scopePermitted = true
743 | end
744 | end
745 | if scopePermitted ~= true then
746 | error("Attempt to set protected member '"..tostring(KEY).."' from outside of class '"..TABLE.__imp__.name.."' is disallowed")
747 | end
748 | end
749 |
750 | -- Conduct edit allowed check
751 | if targetMember.value_type == UPPERCLASS_TYPE_ANY then
752 | editPermitted = true
753 | elseif targetMember.value_type.string == type(VALUE) then
754 | editPermitted = true
755 | else
756 | error("Attempt to set member '"..tostring(KEY).."' in class '"..TABLE.__imp__.name.."' of type '"..targetMember.value_type.string.."' with value type '"..tostring(type(VALUE)).."' is disallowed")
757 | end
758 |
759 | -- Conduct edit
760 | if editPermitted == true then
761 | classinst.memberValueOverrides[KEY] = {value=VALUE}
762 | end
763 | end
764 |
765 |
766 | --
767 | -- ClassRuntimeMetatable __tostring method
768 | --
769 | function ClassRuntimeMetatable.__tostring(TABLE)
770 | local classimp = rawget(TABLE, '__imp__')
771 | local classinst = rawget(TABLE, '__inst__')
772 |
773 | if upperclass:getClassMember(TABLE, '__tostring') ~= nil then
774 | local tostringMetamethodRetVal = upperclass:getClassMember(TABLE, '__newindex').value_default(TABLE)
775 | if tostringMetamethodRetVal == UPPERCLASS_DEFAULT_BEHAVIOR then
776 | return "class "..classimp.name
777 | else
778 | return tostringMetamethodRetVal
779 | end
780 | else
781 | return "class "..classimp.name
782 | end
783 | end
784 | --
785 | -- Return upperclass
786 | --
787 | return upperclass
--------------------------------------------------------------------------------
/xml/lib/utils.lua:
--------------------------------------------------------------------------------
1 | local upperclass = require(LIBXML_REQUIRE_PATH..'lib.upperclass')
2 |
3 | --
4 | -- Define Class
5 | --
6 | local utils = upperclass:define("utils")
7 |
8 | --
9 | -- Trims a string
10 | --
11 | function public:trim(STRING)
12 | if STRING ~= nil then
13 | return STRING:match'^()%s*$' and '' or STRING:match'^%s*(.*%S)'
14 | end
15 | end
16 |
17 | --
18 | -- Generates a UUID
19 | --
20 | function public:uuid()
21 | local chars = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}
22 | local uuid = {[9]="-",[14]="-",[15]="4",[19]="-",[24]="-"}
23 | local r, index
24 | for i = 1,36 do
25 | if(uuid[i]==nil)then
26 | -- r = 0 | Math.random()*16;
27 | r = math.random (16)
28 | if(i == 20 and BinDecHex)then
29 | -- (r & 0x3) | 0x8
30 | index = tonumber(Hex2Dec(BMOr(BMAnd(Dec2Hex(r), Dec2Hex(3)), Dec2Hex(8))))
31 | if(index < 1 or index > 16)then
32 | print("WARNING Index-19:",index)
33 | return UUID() -- should never happen - just try again if it does ;-)
34 | end
35 | else
36 | index = r
37 | end
38 | uuid[i] = chars[index]
39 | end
40 | end
41 | return table.concat(uuid)
42 | end
43 |
44 | --
45 | -- Literalizes a string
46 | --
47 | function public:literalize(STRING)
48 | text, occur = STRING:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", function(c)
49 | return "%" .. c
50 | end)
51 | return self:trim(text)
52 | end
53 |
54 | --
55 | -- Splits a string by delim
56 | --
57 | function public:split(STRING, PATTERN)
58 | local t = {} -- NOTE: use {n = 0} in Lua-5.0
59 | local fpat = "(.-)" .. PATTERN
60 | local last_end = 1
61 | local s, e, cap = STRING:find(fpat, 1)
62 |
63 | while s do
64 | if s ~= 1 or cap ~= "" then
65 | table.insert(t,cap)
66 | end
67 | last_end = e+1
68 | s, e, cap = STRING:find(fpat, last_end)
69 | end
70 |
71 | if last_end <= #STRING then
72 | cap = STRING:sub(last_end)
73 | table.insert(t, cap)
74 | end
75 |
76 | return t
77 | end
78 |
79 | --
80 | -- Return class
81 | --
82 | return upperclass:compile(utils)
--------------------------------------------------------------------------------