- Joined
- Jul 10, 2007
- Messages
- 6,306
At the core of this resource is the data, the allocator, and the address handling. The address handling is for tracking leaks. It makes sense for this feature to go with the Allocator.
Above this are the algorithms. The behaviors work with this data and with each other. Element is controlled by Collection.
Next, we have the debug library, which is used by the main script. The main script checks for errors before going into the core library.
JASS:
/*
* Node
*
* Provides direct access to data shared between Element and Collection.
* Manages addresses in debug mode.
* Infers whether a node is an element or a collection in debug mode.
*
********************************************************************************************
*
* API
*
* Node next
* Node prev
* Node collection
* debug MemoryMonitor address
*
* readonly boolean next_has
* readonly boolean prev_has
* debug readonly boolean collection_has
* debug readonly boolean address_has
*
* method next_clear takes nothing returns nothing
* method prev_clear takes nothing returns nothing
* method collection_clear takes nothing returns nothing
* method address_clear takes nothing returns nothing
*
* debug readonly boolean isCollection
* debug readonly boolean isElement
* debug readonly boolean allocated
* readonly boolean isNull
*
* static method create takes nothing returns thistype
* method destroy returns nothing
* static method destroyRange takes thistype start, thistype end returns nothing
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
*******************************************************************************************/
private keyword Node
private keyword Element
private keyword Collection
struct Node extends array
private static integer instanceCount = 0
/* element to collection */
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "collection", "thistype")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "next", "thistype")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "prev", "thistype")
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "address", "MemoryMonitor")
endif
static if DEBUG_MODE and LIBRARY_ErrorMessage then
public method operator isCollection takes nothing returns boolean
return collection == -1
endmethod
public method operator isElement takes nothing returns boolean
return collection > 0
endmethod
public method operator allocated takes nothing returns boolean
return collection != 0
endmethod
endif
public method operator isNull takes nothing returns boolean
return this == 0
endmethod
public static method create takes nothing returns thistype
local thistype this = thistype(0).next
if (this == 0) then
set this = instanceCount + 1
set instanceCount = this
else
set thistype(0).next = next
endif
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
set address = MemoryMonitor.create("Node")
endif
return this
endmethod
public method destroy takes nothing returns nothing
set next = thistype(0).next
set thistype(0).next = this
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
call address.destroy()
endif
endmethod
public static method destroyRange takes thistype start, thistype end returns nothing
set end.next = thistype(0).next
set thistype(0).next = start
static if DEBUG_MODE and LIBRARY_ErrorMessage then
loop
static if LIBRARY_MemoryAnalysis then
call start.address.destroy()
endif
exitwhen integer(start) == integer(end)
set start = start.next
endloop
endif
endmethod
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
//! runtextmacro MEMORY_ANALYSIS_FIELD_OLD("next", "instanceCount")
public static method calculateMemoryUsage takes nothing returns integer
return calculateAllocatedMemory__next()
endmethod
public static method getAllocatedMemoryAsString takes nothing returns string
return allocatedMemoryString__next()
endmethod
endif
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("collection")
//! runtextmacro INITIALIZE_TABLE_FIELD("next")
//! runtextmacro INITIALIZE_TABLE_FIELD("prev")
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
//! runtextmacro INITIALIZE_TABLE_FIELD("address")
endif
endmethod
implement Init
endstruct
Above this are the algorithms. The behaviors work with this data and with each other. Element is controlled by Collection.
JASS:
/*
* Element extends Node
*
********************************************************************************************
*
* IMPORTS
*/
//! import "List\HtNt\data\Node.j"
/*
********************************************************************************************
*
* API
*
* readonly Node node
*
* Element next
* Element prev
*
* readonly Collection collection
* readonly boolean isNull
*
* static method create takes Collection collection returns thistype
* method destroy takes nothing returns nothing
* static method destroyRange takes thistype start, thistype end returns nothing
*
*******************************************************************************************/
struct Element extends array
public method operator Node takes nothing returns Node
return this
endmethod
public method operator next takes nothing returns Element
return Node.next
endmethod
public method operator next= takes Element element returns nothing
set Node.next = element
endmethod
public method operator prev takes nothing returns Element
return Node.prev
endmethod
public method operator prev= takes Element element returns nothing
set Node.prev = element
endmethod
public method operator collection takes nothing returns Collection
return Node.collection
endmethod
public method operator isNull takes nothing returns boolean
return Node.isNull
endmethod
public static method create takes Collection collection returns thistype
local thistype this = Node.create()
set Node.collection = collection
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
call Node(collection).address.monitor("Element", Node.address)
endif
return this
endmethod
public method destroy takes nothing returns nothing
call Node.destroy()
endmethod
public static method destroyRange takes thistype start, thistype end returns nothing
call Node.destroyRange(start, end)
endmethod
endstruct
JASS:
/*
* Collection extends Node
*
********************************************************************************************
*
* IMPORTS
*/
//! import "List\HtNt\data\Node.j"
//! import "List\HtNt\data\Element.j"
/*
********************************************************************************************
*
* API
*
* Readonly Node node
*
* Element first
* Element last
*
* readonly boolean empty
* readonly boolean isNull
*
* static method create takes nothing returns Collection
* method destroy takes nothing returns nothing
*
* method clear takes nothing returns nothing
*
* method push takes nothing returns thistype
* method enqueue takes nothing returns thistype
* method pop takes nothing returns nothing
* method dequeue takes nothing returns nothing
* method remove takes Element element returns nothing
*
*******************************************************************************************/
struct Collection extends array
public method operator Node takes nothing returns Node
return this
endmethod
public method operator first takes nothing returns Element
return Node(this).next
endmethod
public method operator first= takes Node element returns nothing
set Node(this).next = element
endmethod
public method operator last takes nothing returns Element
return Node(this).prev
endmethod
public method operator last= takes Node element returns nothing
set Node(this).prev = element
endmethod
public method operator isNull takes nothing returns boolean
return Node.isNull
endmethod
public method operator empty takes nothing returns boolean
return first.isNull
endmethod
public static method create takes nothing returns thistype
local thistype this = Node.create()
set first = 0
set last = 0
static if DEBUG_MODE and LIBRARY_ErrorMessage then
set Node.collection = -1
endif
return this
endmethod
public method clear takes nothing returns nothing
if (not empty) then
call Element.destroyRange(first, last)
set first = 0
set last = 0
endif
endmethod
public method destroy takes nothing returns nothing
if (not empty) then
call Element.destroyRange(first, last)
endif
call Node.destroy()
endmethod
public method push takes nothing returns thistype
local Element element = Element.create(this)
if (empty) then
set first = element
set last = element
set element.next = 0
set element.prev = 0
else
set element.next = first
set element.prev = 0
set first.prev = element
set first = element
endif
return element
endmethod
public method enqueue takes nothing returns thistype
local Element element = Element.create(this)
if (empty) then
set first = element
set last = element
set element.next = 0
set element.prev = 0
else
set element.prev = last
set element.next = 0
set last.next = element
set last = element
endif
return element
endmethod
public method pop takes nothing returns nothing
local Element first = this.first.next
call this.first.destroy()
set this.first = first
if (first == 0) then
set last = 0
else
set first.prev = 0
endif
endmethod
public method dequeue takes nothing returns nothing
local Element last = this.last.prev
call this.last.destroy()
set this.last = last
if (last == 0) then
set first = 0
else
set last.next = 0
endif
endmethod
public method remove takes Element element returns nothing
if (element.prev == 0) then
set first = element.next
else
set element.prev.next = element.next
endif
if (element.next == 0) then
set last = element.prev
else
set element.next.prev = element.prev
endif
call element.destroy()
endmethod
endstruct
Next, we have the debug library, which is used by the main script. The main script checks for errors before going into the core library.
JASS:
/*
* Assertions
*
********************************************************************************************
*
* DEBUG ONLY */static if DEBUG_MODE and LIBRARY_ErrorMessage then/*
*/
private struct ErrorMessage extends array
public static constant string ACCESS_NULL = "Attempted To Access Null Element."
public static constant string ACCESS_COLLECTION = "Attempted To Access Collection, Expecting Element."
public static constant string ACCESS_ELEMENT = "Attempted To Access Element, Expecting Collection."
public static constant string ACCESS_INVALID_ELEMENT = "Attempted To Access Invalid Element."
public static constant string ACCESS_INVALID_COLLECTION = "Attempted To Access Invalid Collection."
public static constant string ACCESS_EMPTY = "Attempted To Access Empty Collection."
endstruct
/*
*******************************************************************************************/
endif
JASS:
/*
* Assertions
*
********************************************************************************************
*
* IMPORTS
*/
//! import "List\HtNt\data\Node.j"
//! import "List\HtNt\data\Element.j"
//! import "List\HtNt\data\Collection.j"
//! import "List\HtNt\debug\ErrorMessages.j"
/*
********************************************************************************************
*
* DEBUG ONLY */static if DEBUG_MODE and LIBRARY_ErrorMessage then/*
*/
private function AssertNull takes string operationName, Node node returns nothing
call ThrowError(node.isNull, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_NULL)
endfunction
private function AssertAllocated takes string operationName, Node node returns nothing
call AssertNull(operationName, node)
call ThrowError(not node.allocated, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_INVALID_ELEMENT)
endfunction
private function AssertElement takes string operationName, Node node returns nothing
call AssertNull(operationName, node)
call ThrowError(node.isCollection, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_COLLECTION)
call ThrowError(not node.isElement, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_INVALID_ELEMENT)
endfunction
private function AssertCollection takes string operationName, Node node returns nothing
call AssertNull(operationName, node)
call ThrowError(node.isElement, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_ELEMENT)
call ThrowError(not node.isCollection, "ListHtNt", operationName, "ListHtNt", node, ErrorMessage.ACCESS_INVALID_COLLECTION)
endfunction
private function AssertCollectionNotEmpty takes string operationName, Collection collection returns nothing
call AssertCollection(operationName, collection)
call ThrowError(collection.first.isNull, "ListHtNt", operationName, "ListHtNt", collection, ErrorMessage.ACCESS_EMPTY)
endfunction
/*
*******************************************************************************************/
endif
JASS:
//! import "Table\main.j"
//! import "TableField\main.j"
//! import "Init\main.j"
library ListHtNt /* v2.0.0.0
************************************************************************************
*
* */ uses /*
*
* */ optional ErrorMessage /* github.com/nestharus/JASS/blob/master/jass/Systems/ErrorMessage/script.j
* */ optional MemoryAnalysis /*
* */ TableField /*
* */ Table /* hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
* */ Init /*
*
************************************************************************************
*
* struct/module ListHtNt
*
* Description
* -------------------------
*
* NA
*
* Fields
* -------------------------
*
* debug readonly MemoryMonitor address
*
* readonly thistype collection
*
* readonly thistype first
* readonly thistype last
*
* readonly thistype next
* readonly thistype prev
*
* readonly boolean sentinel
* - exit loop when this becomes true
*
* readonly boolean isNull
*
* Methods
* -------------------------
*
* static method create takes nothing returns thistype
* method destroy takes nothing returns nothing
* - May only destroy lists
*
* method push takes nothing returns thistype
* method enqueue takes nothing returns thistype
*
* method pop takes nothing returns nothing
* method dequeue takes nothing returns nothing
*
* method remove takes nothing returns nothing
*
* method clear takes nothing returns nothing
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************/
//! import "List\HtNt\data\Node.j"
//! import "List\HtNt\data\Element.j"
//! import "List\HtNt\data\Collection.j"
//! import "List\HtNt\debug\ErrorMessages.j"
//! import "List\HtNt\debug\Assertions.j"
// Assertion Logic
struct ListHtNt extends array
private method operator Node takes nothing returns Node
return this
endmethod
private method operator Element takes nothing returns Element
return this
endmethod
private method operator Collection takes nothing returns Collection
return this
endmethod
public method operator isNull takes nothing returns boolean
return Node.isNull
endmethod
public method operator sentinel takes nothing returns boolean
return isNull
endmethod
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
public method operator address takes nothing returns MemoryMonitor
call AssertAllocated("address", this)
return Node.address
endmethod
endif
public method operator collection takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertElement("collection", this)
endif
return Element.collection
endmethod
public method operator next takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertElement("next", this)
endif
return Element.next
endmethod
public method operator prev takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertElement("prev", this)
endif
return Element.prev
endmethod
public method operator first takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("first", this)
endif
return Collection.first
endmethod
public method operator last takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("last", this)
endif
return Collection.last
endmethod
public static method create takes nothing returns thistype
return Collection.create()
endmethod
public method destroy takes nothing returns nothing
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("destroy", this)
endif
call Collection.destroy()
endmethod
method push takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("push", this)
endif
return Collection.push()
endmethod
method enqueue takes nothing returns thistype
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("enqueue", this)
endif
return Collection.enqueue()
endmethod
method pop takes nothing returns nothing
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollectionNotEmpty("pop", this)
endif
call Collection.pop()
endmethod
method dequeue takes nothing returns nothing
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollectionNotEmpty("dequeue", this)
endif
call Collection.dequeue()
endmethod
method remove takes nothing returns nothing
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertElement("remove", this)
endif
call Element.collection.remove(this)
endmethod
method clear takes nothing returns nothing
static if DEBUG_MODE and LIBRARY_ErrorMessage then
call AssertCollection("clear", this)
endif
call Collection.clear()
endmethod
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
public static method calculateMemoryUsage takes nothing returns integer
return Node.calculateMemoryUsage()
endmethod
public static method getAllocatedMemoryAsString takes nothing returns string
return Node.getAllocatedMemoryAsString()
endmethod
endif
endstruct
module ListHtNt
public method operator sentinel takes nothing returns boolean
return ListHtNt(this).sentinel
endmethod
public method operator isNull takes nothing returns boolean
return ListHtNt(this).isNull
endmethod
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
public method operator address takes nothing returns MemoryMonitor
return ListHtNt(this).address
endmethod
endif
public method operator collection takes nothing returns thistype
return ListHtNt(this).collection
endmethod
public method operator next takes nothing returns thistype
return ListHtNt(this).next
endmethod
public method operator prev takes nothing returns thistype
return ListHtNt(this).prev
endmethod
public method operator first takes nothing returns thistype
return ListHtNt(this).first
endmethod
public method operator last takes nothing returns thistype
return ListHtNt(this).last
endmethod
static method create takes nothing returns thistype
return ListHtNt.create()
endmethod
public method destroy takes nothing returns nothing
call ListHtNt(this).destroy()
endmethod
method push takes nothing returns thistype
return ListHtNt(this).push()
endmethod
method enqueue takes nothing returns thistype
return ListHtNt(this).enqueue()
endmethod
method pop takes nothing returns nothing
call ListHtNt(this).pop()
endmethod
method dequeue takes nothing returns nothing
call ListHtNt(this).dequeue()
endmethod
method remove takes nothing returns nothing
call ListHtNt(this).remove()
endmethod
method clear takes nothing returns nothing
call ListHtNt(this).clear()
endmethod
static if DEBUG_MODE and LIBRARY_ErrorMessage and LIBRARY_MemoryAnalysis then
public static method calculateMemoryUsage takes nothing returns integer
return ListHtNt.calculateMemoryUsage()
endmethod
public static method getAllocatedMemoryAsString takes nothing returns string
return ListHtNt.getAllocatedMemoryAsString()
endmethod
endif
endmodule
endlibrary