| 01-08-2004, 01:08 AM | #1 |
I've made some experiments with return bug-based functions and here are results: 1. Not only handle anchestors have handles, but strings, reals and booleans also have! I could hardly believe my eyes... 2. Every new string declaration as well as string union operator causes memory leaks! This is example: Code:
[color=skyblue] function SomeFunc takes nothing returns nothing local string Str = [/color][color=limegreen]"Hello "[/color] + [color=limegreen]"World!"[/color][color=skyblue] endfunction [/color] When being called, SomeFunc() allocates 3 strings and 3 handles corresponding to them in memory: 1. "Hello " 2. "World!" 3. "Hello World!" Every "+" operator allocates handles for both operands and one handle for result! And every time string is declared or redeclared it leaks memory! For example: Code:
[color=skyblue] function MyFunc takes nothing returns nothing local function Str = [/color][color=limegreen]"AAAA"[/color][color=skyblue] set Str = [/color][color=limegreen]"BBBB"[/color][color=skyblue] set Str = [/color][color=limegreen]"CCCC"[/color][color=skyblue] set Str = [/color][color=limegreen]"DDDD"[/color][color=skyblue] endfunction [/color] I have noticed one thing: If you declare string, but another string contains the same data was already declared, String2Handle() doesn't allocate additional handle. It returns handle to existing string. I guess Blizzard made this for saving memory. 3. Warcraft doesn't use direct memory handles. You know well it's too unsafe so Blizzard couldn't do that! Handles are allocated in "declaration order". 4. Reals have handles too! Try using R2H() and H2R() function to ensure. But real handles are very big numbers unlike string / unit handles. Is it possible to be not a handle but real data coded into integer? I haven't understood this yet. RB open incredible coding abilities! Transferring and returnings arrays into / out ANY function is POSSIBLE. I'm translating short report about this... I'll post it tomorrow! ------------------------------------------------- Here's example of C-styled Format function which takes 2 strings: one contains string to be displayed ("Data String") and another contains untypized handles array converted to string ("Handles Array"). Array contains handles can be created using Object2F() functions - I2F(), R2F(), S2F() and P2F() functions. This functions supports only several types of data:
How to use this? You have string like this: "Player %p has %i gold, %i lumber and his hero has %r% of health..." So just call: Code:
[color=skyblue]call Format( [color=limegreen]"Player %p has %i gold, %i lumber and his hero has %r% of health..."[/color], P2F(udg_Player) + I2F(udg_PlayerGold) + I2F(udg_PlayerLumber) + R2F(udg_HealthPercent)) [/color] So you get string like this: "Player Cacodemon has 500 gold, 100 lumber and his hero has 75.00% of health..." "Cacodemon", 500, 100, "75.00" are values stored in corresponding variables. If your Handle String have less handles than Data String, formatting symbols which don't have corresponding handles are displayed "as is". You can format strings contains as many handles of any type as you wish. Be sure that actual types of handles in Handle String are equal to handles types in Data string! This is its code including standart RB-functions: Code:
[color=skyblue]
function S2H takes string S returns integer
return S
return 0
endfunction
function H2S takes integer H returns string
return H
return ""
endfunction
function R2H takes real R returns integer
return R
return 0
endfunction
function H2R takes integer H returns real
return H
return 0.0
endfunction
function P2H takes player P returns integer
return P
return 0
endfunction
function H2P takes integer H returns player
return H
return null
endfunction
function I2F takes integer I returns string
return I2S(I) + " "
endfunction
function R2F takes real R returns string
return I2S(R2H(R)) + " "
endfunction
function S2F takes string S returns string
return I2S(S2H(S)) + " "
endfunction
function P2F takes player P returns string
return I2S(P2H(P)) + " "
endfunction
function Char takes string Str, integer Index returns string
return SubString(Str, Index, Index + 1)
endfunction
function CPos takes string M, string Sub, integer Index returns integer
loop
exitwhen (Char(M,Index) == Sub) or (Char(M,Index) == "")
set Index = Index + 1
endloop
return Index
endfunction
function Format takes string DStr, string HStr returns string
local string Result = ""
local integer DSize = CPos(DStr, "", 0)
local integer HSize = CPos(HStr, "", 0)
local integer PrevH = 0
local integer NextH = -1
local integer DType = 0
local integer Ref = 0
local string Token
if HStr == "" then
return DStr
endif
loop
exitwhen Ref >= DSize
if Char(DStr, Ref) == "%" then
set DType = CPos("iprs", Char(DStr, Ref + 1), 0)
if (DType < 4) then
set Ref = Ref + 1
set PrevH = NextH + 1
if PrevH < HSize then
set NextH = CPos(HStr, " ", PrevH)
set PrevH = S2I(SubString(HStr, PrevH, NextH + 1))
if DType == 3 then
set Token = H2S(PrevH)
elseif DType == 2 then
set Token = R2S(H2R(PrevH))
elseif DType == 1 then
set Token = GetPlayerName(H2P(PrevH))
else
set Token = I2S(PrevH)
endif
else
set Token = SubString(DStr, Ref - 1, Ref + 2)
endif
else
set Token = Char(DStr, Ref)
endif
else
set Token = Char(DStr, Ref)
endif
set Result = Result + Token
set Ref = Ref + 1
endloop
return Result
endfunction
[/color]You can add additional handle types to this function, for example:
I guess it's very, very useful... Starcraftfreak: Can you add this function to your UMSWE? --------------------------------- How to transfer arrays into functions... (No actual arrays but strings contains several handles) Just convert all handles to string, handles can be divided by space. You can place every handle's type before it: For example, "I100 S26 R1237464 U13434 I343 " Means:
Handle values can be got using I2S(Object2H(Object)) + " " functions. See example (S2F(), R2F() etc, but they don't add data type before handle) You function should take string argument and process this string inside it. Algorythm is very simple (see previous example). You can process "arrays" contain several data types. Your function can return this "handle string" as well... I know this method is really stupid but only it allows you to transfer "arrays"... |
| 01-08-2004, 02:17 AM | #2 |
This is Format() example... Type "Info" just in game... Every 5 seconds amount of resources is random-changed so you can see the difference in displayed values... |
| 01-08-2004, 09:14 AM | #3 |
Again I feel obliged to caution everyone NOT to use the return bug. There is always a good alternative solution. ALWAYS. I don't really see why you need the return bug to create the format function. In particular, this function seems useless: Code:
function R2F takes real R returns string return I2S(R2H(R)) + " " endfunction function R2F takes real R returns string return R2S(r) + " " endfunction Just use the above function and then don't decode the real in the format function. Same for other values. Why pass the player handle using return bug, when you can just put the player name in the string? Granted, you'll probably have to use a different delimiter instead of a single space, but that's not the point :) Also, I'm not sure if reals are handles. Might be they are just 4 byte floats. Same for booleans. Try converting a real big real (lots of digits: 20+) to an integer and back again. If it fails, reals are probably stored as doubles (8 bytes). If not, probably floats (4 bytes, same as ints). Try changing the integer you get from the return bug by increasing it by one and see what happens to the result. It should be a real still, just a different number. If war3 crashes or something, they might be hanldes after all. |
| 01-08-2004, 12:19 PM | #4 |
Format() is not so good example of RB use. You can convert your data to string, not using return bug then process that string. But I've tried to show how "handle strings" can be used to process "array imitations" into function. Sometimes it can be useful. As for reals, their precision depends on value: 0.12345678 is stored without precision loss, but 100000000000.12234 will be truncated to: 100000000000.0. emote_sweat |
| 01-08-2004, 01:06 PM | #5 |
I like your idea about converting an array to a string to pass it as a parameter. It's a really interesting idea. |
| 01-08-2004, 01:57 PM | #6 |
I think using the heap is a better mechanism for passing arrays to functions than using a string. Especially it is more efficient. Reals are stored as x*(2^y) . Thats why the precision behaves in the way you described. |
| 01-08-2004, 03:17 PM | #7 |
AIAndy: Please write your "heap algorythm" here... I don't understand what you're talking about... P.S. Thank you for Real storage method. |
| 01-08-2004, 03:48 PM | #8 |
http://www.wc3campaigns.com/forums/s...threadid=38216 The heap that was developed in the last JASS Challenge. Look at the end of the thread for instructions on how to use it. The heap provides a way to retrieve memory and return it again once it is not needed any more. The memory is accessed by pointers which can be passed to any function (and returned of course too) as they are simple integers. |
| 01-08-2004, 08:28 PM | #9 |
Still you did a good job finding all that out Cacodemon:D |
| 01-09-2004, 02:28 AM | #10 |
Right earlier versions of my DT4:A use to pass strings of information (using the return bug and mostly ints). WhicH I converted to arrays. However, as the code for each item became more and more complex I found an easier implementation to be multiple strings per item. I figured the database system was much easier for the end user as well. Return bug of strings working is nice though. |
| 01-09-2004, 10:05 AM | #11 |
I think new heap system can be created using RB features. For example, you can store heap data as string and process heaps using their string handles. This method independs on global variables. There's only one problem - string handle is changed after every heap modification so it's better to store these handles in integer array and use cell index as heap. |
| 01-11-2004, 01:29 AM | #12 |
is there any way you could develop / post a new heap system with the method you described in ur post above, i think it would be more memory-efficient and easier to implement than the other 2 uses. |
| 01-11-2004, 03:34 PM | #13 |
If Warcraft modding community really needs this I can try a bit later... |
