/* * Dictionary v1.2 * * Контейнер, представляющий массив с произвольным индексатором. * Построен на основе бинарного древа. * * © 2011 Sir Nikolas \\ WarCraft3FT.info * */ //! textmacro DeclareDictionary takes indexator_type, value_type, funcs, size library_once Dictionary$indexator_type$$value_type$ uses $funcs$ private /* */ function interface func takes $indexator_type$ index, $value_type$ value returns nothing private struct Node[$size$] static integer Max = 0 static boolean ForEach_Continue = true static $indexator_type$ array indexAr static $value_type$ array valueAr boolean Empty $indexator_type$ index $value_type$ value Node n1 Node n2 static method create takes nothing returns thistype local thistype this = 0 loop if this == Max then if Max > $size$ then debug call DisplayTextToPlayer(GetLocalPlayer(), .0, .0, /* */ "Невозможно создать узел объекта Dictionary.") return -1 endif set Max = Max + 1 exitwhen true endif exitwhen this.Empty set this = this + 1 endloop set this.Empty = false set this.n1 = -1 set this.n2 = -1 return this endmethod method destroy takes nothing returns nothing if n1 != -1 then call n1.destroy() endif if n2 != -1 then call n2.destroy() endif set Empty = true endmethod method count takes nothing returns integer local integer i = 1 if n1 != -1 then set i = n1.count() + 1 endif if n2 != -1 then return i + n2.count() endif return i endmethod method to_array takes integer n returns integer if n1 != -1 then set n = n1.to_array(n) endif if value != thistype(-1).value then set indexAr[n] = index set valueAr[n] = value set n = n + 1 endif set Empty = true//call .destroy() if n2 != -1 then return n2.to_array(n) endif return n endmethod static method from_array takes integer n, integer jump, integer min, integer max returns thistype local thistype this = create() if n - jump >= min then set this.n1 = from_array(n - jump, (jump + 1) / 2, min, n) endif set this.index = indexAr[n] set this.value = valueAr[n] if n + jump < max then set this.n2 = from_array(n + jump, (jump + 1) / 2, n + 1, max) endif return this endmethod method for_each takes func callback returns nothing if n1 != -1 then call n1.for_each(callback) endif if ForEach_Continue and value != thistype(-1).value then call callback.evaluate(index, value) endif if ForEach_Continue and n2 != -1 then call n2.for_each(callback) endif endmethod endstruct private struct ExistsStruct extends array method operator [] takes $indexator_type$ index returns boolean local Node n = this if n == -1 then return false endif loop if $funcs$_equal(index, n.index) then return true elseif $funcs$_less(index, n.index) then if n.n1 == -1 then return false endif set n = n.n1 elseif n.n2 == -1 then return false else set n = n.n2 endif endloop //Исполнение никогда не дойдет до этого места return false endmethod endstruct struct Dictionary_$indexator_type$_$value_type$ extends array private static integer Max = 1 private boolean Empty private Node root static method Create takes nothing returns thistype local thistype this = 1 loop if this == Max then if Max > 8191 then debug call DisplayTextToPlayer(GetLocalPlayer(), .0, .0, /* */ "Невозможно создать узел объекта Dictionary.") return 0 endif set Max = Max + 1 exitwhen true endif exitwhen this.Empty set this = this + 1 endloop set this.Empty = false set this.root = -1 return this endmethod method Destroy takes nothing returns nothing if root != -1 then call root.destroy() endif set Empty = true endmethod method operator [] takes $indexator_type$ index returns $value_type$ local Node n = root if n == -1 then return Node(-1).value endif loop if $funcs$_equal(index, n.index) then return n.value elseif $funcs$_less(index, n.index) then if n.n1 == -1 then return Node(-1).value endif set n = n.n1 elseif n.n2 == -1 then return Node(-1).value else set n = n.n2 endif endloop //Исполнение никогда не дойдет до этого места return Node(-1).value endmethod method operator []= takes $indexator_type$ index, $value_type$ value returns nothing local Node n = root local Node parent if n == -1 then if value != Node(-1).value then set root = Node.create() set root.index = index set root.value = value endif else loop if $funcs$_equal(index, n.index) then if value == Node(-1).value and n.n1 == -1 and n.n2 == -1 then set n.Empty = true//call n.destroy() if n == root then set root = -1 elseif n == parent.n1 then set parent.n1 = -1 else set parent.n2 = -1 endif else set n.value = value endif return elseif $funcs$_less(index, n.index) then if n.n1 == -1 then if value != Node(-1).value then set n.n1 = Node.create() set n.n1.index = index set n.n1.value = value endif return endif set parent = n set n = n.n1 elseif n.n2 == -1 then if value != Node(-1).value then set n.n2 = Node.create() set n.n2.index = index set n.n2.value = value endif return else set parent = n set n = n.n2 endif endloop endif endmethod method Clear takes nothing returns nothing if root != -1 then call root.destroy() set root = -1 endif endmethod method operator Count takes nothing returns integer if root == -1 then return 0 endif return root.count() endmethod method operator Exists takes nothing returns ExistsStruct return root endmethod method ForEach takes func callback returns nothing if root != -1 then if root.n1 != -1 then call root.n1.for_each(callback) endif if Node.ForEach_Continue and root.value != Node(-1).value then call callback.evaluate(root.index, root.value) endif if Node.ForEach_Continue and root.n2 != -1 then call root.n2.for_each(callback) endif set Node.ForEach_Continue = true endif endmethod static method Break takes nothing returns nothing set Node.ForEach_Continue = false endmethod method Rebuild takes nothing returns nothing local integer size if root != -1 then set size = root.to_array(0) set root = Node.from_array((size - 1) / 2, (size - size / 2 + 1) / 2, 0, size) endif endmethod endstruct endlibrary //! endtextmacro