| 08-07-2007, 02:23 PM | #1 |
Written in Good Old Fashioned Jass... This code has a combination of Memory Manager Techniques and Pointer Techniques. The concept is that you are passing around a handle to a gamecache and an integer that is a reference to the location of the string within the gamecache's stored string. The header is behind that location so going backwards reveals other information. A pointer is described as follows: below each identifier is a length in characters of the identifier ptrID: + customvalue + pointernext + stringlength + stringvalue -(6)-------(21)-----------(4)------------(3)-------(max. 999) ptrID: >> identifies the beginning of the header customvalue >> any 21 character string value, usually a description of the variable pointernext >> could be used in a linked list, like to refer to the next string stringlength >> length of the string stringvalue >> the value given (max. length = 999) Code:
//UTILITY FUNCTIONS
function getHandle takes gamecache gc returns integer
return gc
return 0
endfunction
function getCache takes integer hCache returns gamecache
return hCache
return null
endfunction
function getPCV takes string PCV returns string
if StringLength(PCV) > 21 then
return SubString(PCV, 0, 20)
else
return PCV
endif
endfunction
function getPN takes integer PN returns string
local string tmp = ""
if PN > 9999 or PN <= 0 then
return "0000"
else
set tmp = I2S(PN)
if StringLength(tmp) == 3 then
set tmp = "0" + tmp
elseif StringLength(tmp) == 2 then
set tmp = "00" + tmp
else
return "0000"
endif
endif
return tmp
endfunction
function getTL takes integer TL returns string
local string tmp = ""
if TL > 999 or TL <= 0 then
return "000"
else
set tmp = I2S(TL)
if StringLength(tmp) == 2 then
set tmp = "0" + tmp
else
return "000"
endif
endif
return tmp
endfunction
//MEMORY MANAGEMENT FUNCTIONS
function CreateMemoryBlock takes integer UniqueID returns integer
return getHandle(InitGameCache(I2S(UniqueID) + ".w3v"))
endfunction
//34 character header on every MemoryManagerUnit
//the format: "ptrID:"(6) + PointerLabel(21) + PointerNext(4) + ThisLength(3)
//STRING POINTER MANAGEMENT FUNCTIONS
//function createString creates a string and returns a pointer
function cS takes string origValue, string PointerCustomValue, integer PointerNext, integer hMemoryBlock returns integer
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local integer ret = 0
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
set ret = StringLength(pArea) + 35
set pArea = pArea + "ptrID:" + getPCV(PointerCustomValue) + getPN(PointerNext) + getTL(StringLength(origValue)) + origValue
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
return ret
endfunction
//function setString
function sS takes string newValue, integer hMemoryObject, integer hMemoryBlock returns nothing
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string PCV = SubString(pArea, hMemoryObject - 27, hMemoryObject - 6)
local string PN = SubString(pArea, hMemoryObject - 7, hMemoryObject - 3)
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
set pArea = SubString(pArea, 0, hMemoryObject - 34) + "ptrID:" + PCV + PN + getTL(StringLength(newValue)) + newValue + SubString(pArea, hMemoryObject + S2I(getTL(StringLength(newValue))), StringLength(pArea))
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
endfunction
//function setStringcustomvalue
function sScv takes string newValue, integer hMemoryObject, integer hMemoryBlock returns nothing
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string SV = SubString(pArea, hMemoryObject, S2I(SubString(pArea, hMemoryObject - 3, hMemoryObject)) + hMemoryObject)
local string PN = SubString(pArea, hMemoryObject - 7, hMemoryObject - 3)
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
set pArea = SubString(pArea, 0, hMemoryObject - 34) + "ptrID:" + getPCV(newValue) + PN + getTL(StringLength(SV)) + SV + SubString(pArea, hMemoryObject + S2I(getTL(StringLength(newValue))), StringLength(pArea))
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
endfunction
//function getStringcustomvalue returns the custom value of a string pointer
function gScv takes integer hMemoryObject, integer hMemoryBlock returns string
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string hMemoryObject_String = I2S(hMemoryObject) //the string form of hMemoryObject
local integer end = 0 //ThisLength + hMemoryObject
if StringLength(pArea) > 0 then
set end = S2I(SubString(pArea, hMemoryObject - 27, hMemoryObject - 6)) + hMemoryObject //retrieves the ThisLength object from the MO header and adds the location onto it
return SubString(pArea, hMemoryObject, end) //retrieves the desired string
endif
return "Error: No Such Pointer" //error message
endfunction
//function getString returns a string from a string pointer
function gS takes integer hMemoryObject, integer hMemoryBlock returns string
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string hMemoryObject_String = I2S(hMemoryObject) //the string form of hMemoryObject
local integer end = 0 //ThisLength + hMemoryObject
if StringLength(pArea) > 0 then
set end = S2I(SubString(pArea, hMemoryObject - 6, hMemoryObject - 3)) + hMemoryObject //retrieves the ThisLength object from the MO header and adds the location onto it
return SubString(pArea, hMemoryObject, end) //retrieves the desired string
endif
return "Error: No Such Pointer" //error message
endfunctionI have only developed the string pointers section. I have not yet written the code to alter the PointerNext header variable, or use it. Additional Description: Pointer Variables/Memory Management None of this has been tested, this is all theoretical. I believe that you could pass the handle of the gamecache without have it be a global variable and then access it from other locations to effect that it is global. Additionally, rather than needing to return a string: a function could simply change the value of the provided string pointer so that the next time it is accessed it uses the value last set. Another possiblilty is that with some changes in the functions, you could pass arrays from one function to the next because they would be pointing to one location and you would specify the index. Are there any corrections to my code? I haven't coded Jass in awhile so it may have mistakes. (This is representative of a memory manager in the fact that this uses pointers, and behind every pointer is a header. Do some operating system development and you will understand that is how a pointer *works* to an extent) Here is an example of my code in action (i have tested the following, with no luck) Code:
function newmsg takes integer message, integer memblock returns nothing call sS(gS(message, memblock) + "!!!!", message, memblock) endfunction function testmsg takes string message returns nothing local integer memblock = CreateMemoryBlock(16) local integer strptr = cS(message, "Display Message", -1, memblock) call newmsg(strptr, memblock) call DisplayTextToForce(GetPlayersAll(), "---------") call DisplayTextToForce(GetPlayersAll(), "|" + gS(strptr, memblock) + "|") call DisplayTextToForce(GetPlayersAll(), "---------") endfunction The above code displays the following --------- --------- for reasons as of now, unknown to me. Does anybody understand what i am doing well enough to find a problem? |
| 08-07-2007, 04:21 PM | #2 |
are u crazy ? =\ string + gamecache fuckedg =\ |
| 08-07-2007, 04:41 PM | #3 |
String leakage much? |
| 08-07-2007, 05:02 PM | #4 |
This will get slooow... Ok but in all honesty. There are other systems for data management out there because using the gamecache just turned out to be inefficient and slow. Furthermore, strings leak, so this system probably won't work too well. Although it may be a good system in theory, this just isn't the environment for it :) I can look through the code though, see if I can find your bug (btw it should display the "|"'s ...) |
| 08-07-2007, 08:50 PM | #5 | |
Quote:
Well if you tell us what drugs were you using while you coded this we could possibly get closer to understanding by reproducing the effects... EDIT: What strikes me most is that you actually do have some programming background, witch only makes this whole thing look even more crazy. |
| 08-07-2007, 09:00 PM | #6 |
It's actually not all that intelligable.. just pretty complicated |
| 08-07-2007, 09:04 PM | #7 |
useless was more the word I was thinking of... |
| 08-08-2007, 12:58 AM | #8 |
What presumably theoretical problem are you trying to solve? This doesn't resemble anything I'd call memory management or pointers. The traditional definition of these to me means C, which has a memory model of a long flat array. Pointer refers to an index in the array while management refers to rationing chunks. |
| 08-08-2007, 02:33 AM | #9 |
To clear up some confusion: this is not meant to be effiecient this is merely a proof-of-concept. A memory manager when it allocates memory, it places a header before the location provided by a pointer. This system is just meant to see if this effect can be replicated in Jass. Ideally the gamecache is the "memory" and the "addresses" are represented by integers. This not really meant to serve a specific purpose; i just wanted to know if something like this was possible in jass. So... Does anybody know how to make what has been described? |
| 08-08-2007, 03:21 AM | #10 |
Again you've described a solution but no problem; you have a proof without a concept. Tell me about the memory manager's motivations, not its actions. |
| 08-08-2007, 08:51 AM | #11 |
There is no problem. It's just an arbitrarily chosen way of arranging and acquiring data if I understand him correctly. He just wants it to work in jass. Correct me if I'm wrong, of course. I guess he's got the theory part worked out already and is just debugging? But Mapz_Maker, it is kind of hard to read through this code and easily see the bug since (and i'm talking for myself here) I don't recognize the system you're working on. It will be microscoping the code and backtracking to see what where goes wrong. Have you tried anymore debugging? Since right now we both start at "it displays nothing". |
| 08-08-2007, 10:58 AM | #12 |
Here, Read This. more specifcally, read the section titled Allocator. That describes essentially what i am doing, although I have made modifications to add additional use into this (such as PointerNext, and CustomValue). Right now, i am trying to figure out if and why the gamecache is not able to be accessed, even with the handle. That is the only "problem" it is more of a bug than a problem though. A memory manager will allocate the needed memory for an object as well as additional memory to store its header info. The header info describes the pointer, such as Size and Protection. To describe my 'format' more imagine this example (the formula is ptrID: + customvalue + pointernext + stringlength + stringvalue) "ptrID:Hello, World---------253715this is awesome" The colors divide the different sections of the 'memory' space. Orange is where the pointer is pointing; it is the value. The header is behind that. This should work, according to theory; but, for some reason it actually displays. Yellow is the length of orange. blue is a 'pointer' to another pointer (like for a linked list). green is the custom value (must be 21 characters). red is a unique identifier so that we can recognize that this is a pointer. --------- | --------- (forgot the "|" on the last one.) NightBreeze is rather correct. I am attempting to remove the bugs that way this arbitrary way of data manipulation will succeed. (which could have some implications) |
| 08-08-2007, 03:46 PM | #13 |
OK, I've looked through your code and I have a few comments on it. But first of all let me show you the biggest bug: JASS:function getPCV takes string PCV returns string if StringLength(PCV) > 21 then return SubString(PCV, 0, 20) endif return PCV endfunction This means that a variable PCV is allowed, but it most certainly is NOT. You will have to fill up the rest of the 21 spaces with -'s and check for them if you want to retrieve the PCV. That or store the PCV's length in the header as well, which doesn't seem an appealing option. After I changed the PCV for the testmsg, it started displaying it. I've also removed the pArea initialisation in the cS function, since it resulted in adding strings up if a string was already stored at that particular memory block. I don't know if this was intentional, but it hindered my debugging. New function: JASS:function getPCV takes string PCV returns string local integer PCVl = StringLength(PCV) //storing length in variable to save time local string tmp = "" local integer i = 0 if PCVl > 21 then return SubString(PCV, 0, 20) else set tmp = PCV loop exitwhen i == 21-PCVl set tmp = tmp + "-" set i = i + 1 endloop endif return tmp endfunction This wasn't the only thing that hindered the system's functionality though; I've changed some more things in the process. I'll look through it some more and send you my updated version, I just thought I'd let you know. Oh, and I disabled the sS function which added the exclamation marks for testing purposes, but it should work fine as well. By the way, it wasn't so hard to do with some debugging msges thrown in. I let every cS overwrite the previous string so that the pointer was always 35 and then in the gS I made it print out the beginning and end indices of the string. Then it hit me. EDIT: More bugs. The default pointer should be 34 because of the 0'th index in a string; there were also some problems with the getPN, getTL and gS function. The sS function works fine, but I'm gonna give it another look. |
| 08-08-2007, 04:23 PM | #14 |
OK. We don't have a paged memory let alone an MMU, but if you are asking if fixed size allocations are possible to implement, the answer is yes, see e.g. vJass. Variable sized are possible too but with no MMU you can't build them out of pages, so you have to do it like DARY. Rewriting either technique to gamecache is trivial and would let you use the C style memory model somewhat more freely than with arrays. If you actually tried to use that much capacity you would be completely hosed. |
| 08-08-2007, 08:18 PM | #15 |
I've finished debugging and updating your code. I left everything I removed from your code in there as comments and also left in some debugging messages for you so you can see it all works. I put comments in the code to explain what I changed and put //debug behind every debugmessage so you can delete them easily. JASS:
//UTILITY FUNCTIONS
//changed the name, personal preference.
function Gamecache2int takes gamecache gc returns integer
return gc
return 0
endfunction
function getCache takes integer hCache returns gamecache
return hCache
return null
endfunction
//Changed it so that it correctly ensures a fixed PCV length.
function getPCV takes string PCV returns string
local integer PCVl = StringLength(PCV) //storing length in variable to save time
local string tmp = ""
local integer i = 0
if PCVl > 21 then
return SubString(PCV, 0, 20)
else
set tmp = PCV
loop
exitwhen i == 21-PCVl
set tmp = tmp + "-"
set i = i + 1
endloop
endif
return tmp
endfunction
//Changed it so that it correctly fixes lengths of 2 and 1 digit.
function getPN takes integer PN returns string
local string tmp = ""
if PN > 9999 or PN <= 0 then
return "0000"
endif
set tmp = I2S(PN)
if StringLength(tmp) == 3 then
set tmp = "0" + tmp
elseif StringLength(tmp) == 2 then
set tmp = "00" + tmp
elseif StringLength(tmp) == 1 then
set tmp = "000" + tmp
endif
call DisplayTextToForce(GetPlayersAll(), "getPN runs, PN is " + tmp) //debug
return tmp
endfunction
//Changed it so that it also fixes up lengths of 1 digit.
function getTL takes integer TL returns string
local string tmp = ""
if TL > 999 or TL <= 0 then
return "000"
endif
set tmp = I2S(TL)
if StringLength(tmp) == 2 then
set tmp = "0" + tmp
elseif StringLength(tmp) == 1 then
set tmp = "00" + tmp
endif
return tmp
endfunction
//MEMORY MANAGEMENT FUNCTIONS
function CreateMemoryBlock takes integer UniqueID returns integer
return Gamecache2int(InitGameCache(I2S(UniqueID) + ".w3v"))
endfunction
//34 character header on every MemoryManagerUnit
//the format: "ptrID:"(6) + PointerLabel(21) + PointerNext(4) + ThisLength(3)
//STRING POINTER MANAGEMENT FUNCTIONS
//function createString creates a string and returns a pointer (changed)
function cS takes string origValue, string PointerCustomValue, integer PointerNext, integer hMemoryBlock returns integer
//I deleted the initialisation of pArea here, because I want the new string
//to overwrite the old one, if only for testing purposes. I don't know why you
//would want to keep the old one though. I'd make an addstring function for that.
//I also changed 35 into 34 because of the 0 index.
local string pArea = ""
local integer ret = 0
call DisplayTextToForce(GetPlayersAll(), "cS runs")
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
set ret = StringLength(pArea) + 34
set pArea = "ptrID:" + getPCV(PointerCustomValue) + getPN(PointerNext) + getTL(StringLength(origValue)) + origValue
call DisplayTextToForce(GetPlayersAll(), pArea) //debug
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
return ret
endfunction
//Why do you include what is before the "ptrID:" and after the end of the
//newvalue of the string? There should be nothing there.
//I also altered some of the constants you were subtracting from hMemoryObject
//because they were incorrect.
//function setString (changed)
function sS takes string newValue, integer hMemoryObject, integer hMemoryBlock returns nothing
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string PCV = SubString(pArea, hMemoryObject - 28, hMemoryObject - 7)
local string PN = SubString(pArea, hMemoryObject - 7, hMemoryObject - 3)
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
call DisplayTextToForce(GetPlayersAll(), "PCV is " + PCV + ", and PN is " + PN)
//This stuff is taken out of the return SubString() part
//SubString(pArea, 0, hMemoryObject - 34) + (obsolete)
//SubString(pArea, hMemoryObject + S2I(getTL(StringLength(newValue))), StringLength(pArea) (obsolete)
set pArea = "ptrID:" + PCV + PN + getTL(StringLength(newValue)) + newValue
call DisplayTextToForce(GetPlayersAll(), "sS runs") //debug
call DisplayTextToForce(GetPlayersAll(), pArea) //debug
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
endfunction
//Same as above.
//function setStringcustomvalue (changed)
function sScv takes string newValue, integer hMemoryObject, integer hMemoryBlock returns nothing
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
local string SV = SubString(pArea, hMemoryObject, S2I(SubString(pArea, hMemoryObject - 3, hMemoryObject-1)) + hMemoryObject)
local string PN = SubString(pArea, hMemoryObject - 7, hMemoryObject - 3)
call FlushStoredString(getCache(hMemoryBlock), "memory", "block")
//This stuff is taken out of the return SubString() part
//SubString(pArea, 0, hMemoryObject - 34) + (obsolete?)
//SubString(pArea, hMemoryObject + S2I(getTL(StringLength(newValue))), StringLength(pArea)) (obsolete?)
set pArea = "ptrID:" + getPCV(newValue) + PN + getTL(StringLength(SV)) + SV
call StoreString(getCache(hMemoryBlock), "memory", "block", pArea)
endfunction
//this next one is supposed to get the pointer label right?
//Maybe it's an idea to use uniform naming throughout the code :)
//I commented out what was unnecessary and changed the SubString() parameters
//function getStringcustomvalue returns the custom value of a string pointer
function gScv takes integer hMemoryObject, integer hMemoryBlock returns string
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
//local string hMemoryObject_String = I2S(hMemoryObject) //the string form of hMemoryObject
//local integer end = 0 //ThisLength + hMemoryObject
if StringLength(pArea) > 0 then
//set end = S2I(SubString(pArea, hMemoryObject - 27, hMemoryObject - 6)) + hMemoryObject //retrieves the ThisLength object from the MO header and adds the location onto it
return SubString(pArea, hMemoryObject-27, hMemoryObject-7) //retrieves the desired string
endif
return "Error: No Such Pointer" //error message
endfunction
//Again I changed subtraction constants and some other stuff.
//One important thing to note is that if the specified end of a substring is a smaller integer than
//the start index, it will return everything up to the end of the string.
//function getString returns a string from a string pointer
function gS takes integer hMemoryObject, integer hMemoryBlock returns string
local string pArea = GetStoredString(getCache(hMemoryBlock), "memory", "block")
//local string hMemoryObject_String = I2S(hMemoryObject) //the string form of hMemoryObject
local integer end = 0 //ThisLength + hMemoryObject
call DisplayTextToForce(GetPlayersAll(), "gS runs, string pointer is " + I2S(hMemoryObject)) //debug
if StringLength(pArea) > 0 then
//set end = S2I(SubString(pArea, hMemoryObject - 3, hMemoryObject-1)) + hMemoryObject -1 //retrieves the ThisLength object from the MO header and adds the location onto it
call DisplayTextToForce(GetPlayersAll(),"pointer is " + I2S(hMemoryObject) + ", end is " + I2S(end)) //debug
return SubString(pArea, hMemoryObject, end) //retrieves the desired string
endif
return "Error: No Such Pointer" //error message
endfunction
function newmsg takes integer message, integer memblock returns nothing
call sS(gS(message, memblock) + "!!!!", message, memblock)
endfunction
function testmsg takes string message returns nothing
local integer memblock = CreateMemoryBlock(16)
local integer strptr = cS(message, "Display Message", 523, memblock)
call DisplayTextToForce(GetPlayersAll(), "this is the testmsg: " + message + " and the pointer is " + I2S(strptr)) //debug
call newmsg(strptr, memblock)
call DisplayTextToForce(GetPlayersAll(), "---------")
call DisplayTextToForce(GetPlayersAll(), "|" + gS(strptr, memblock) + "|")
call DisplayTextToForce(GetPlayersAll(), "---------")
endfunction
I haven't tested the sScv and gScv yet, but they seem to be correct now. I leave the testing up to you. Hope it all works out. |
