├── 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 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
Node TypeDescriptionChildren
DocumentRepresents the entire document (the root-node of the DOM tree)Element (max. one), ProcessingInstruction, Comment, DocumentType
DocumentFragmentRepresents a "lightweight" Document object, which 32 | can hold a portion of a documentElement, ProcessingInstruction, Comment, Text, CDATASection, 34 | EntityReference
DocumentTypeProvides an interface to the entities defined for the 39 | documentNone
ProcessingInstructionRepresents a processing instructionNone
EntityReferenceRepresents an entity referenceElement, ProcessingInstruction, Comment, Text, CDATASection, 51 | EntityReference
ElementRepresents an elementElement, Text, Comment, ProcessingInstruction, CDATASection, 57 | EntityReference
AttrRepresents an attributeText, EntityReference
TextRepresents textual content in an element 67 | or attributeNone
CDATASectionRepresents a CDATA section in a document (text that will 73 | NOT be parsed by a parser)None
CommentRepresents a commentNone
EntityRepresents an entityElement, ProcessingInstruction, Comment, Text, CDATASection, 85 | EntityReference
NotationRepresents a notation declared in the DTDNone
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 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 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 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 |
Node TypenodeName returnsnodeValue returns
Document#documentnull
DocumentFragment#document fragmentnull
DocumentTypedoctype namenull
EntityReferenceentity reference namenull
Elementelement namenull
Attrattribute nameattribute value
ProcessingInstructiontargetcontent of node
Comment#commentcomment text
Text#textcontent of node
CDATASection#cdata-sectioncontent of node
Entityentity namenull
Notationnotation namenull
165 | 166 | # NodeTypes - Named Constants 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 |
NodeTypeNamed Constant
1ELEMENT_NODE
2ATTRIBUTE_NODE
3TEXT_NODE
4CDATA_SECTION_NODE
5ENTITY_REFERENCE_NODE
6ENTITY_NODE
7PROCESSING_INSTRUCTION_NODE
8COMMENT_NODE
9DOCUMENT_NODE
10DOCUMENT_TYPE_NODE
11DOCUMENT_FRAGMENT_NODE
12NOTATION_NODE
-------------------------------------------------------------------------------- /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 | 31 | ... 32 | 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) --------------------------------------------------------------------------------