Any restrictions on SaveState()?

Monkey Forums/Monkey Programming/Any restrictions on SaveState()?

GfK(Posted 2011) [#1]
I'm having ongoing problems with this, using HTML5/Chrome, though I'm not sure if other targets are affected

SaveState() works fine in any test code I come up with, but when I'm using my filesystem (which is part of Diddy now), odd things start to happen.

First off, the file structure is thus; A file header "MKYDATA". After that I have an Integer which indicates the number of 'files' that have been saved (using some bit-shifting and converting to strings). After that comes the file data; length of filename (Int), filename itself (String), length of file data (Int), file data itself (String).

This all works fine.... if I hit Refresh in the browser it'll work all day long, until I've closed the browser and reopened it. After that, LoadState only contains "MKDATA" and then indicates one file (Which is correct!), but the file data is gone. Why?!

Now, the way I'm converting from an Int to a String, is to split the Int into its four component bytes, and convert each of those to a single String character (potentially anything from 0-255). Doing it this way means that an Int will always be stored in four bytes.

I cannot see any errors in my code at all (except for a few calls to Set which maybe should have been Insert - these haven't been changed in Diddy yet). So my only other guess is that SaveState does not like or support characters beyond a certain range. I've done a load of tests on this though and cannot find evidence to support the theory.

I would really like some advice on any limitations SaveState might have, as well as finding out whether it supports Unicode or not. (That is a HUGE problem, if so).

Test code:


filesystem.monkey


If you run this code, it will create and save one file called "test.bin", of 1024 bytes. Hit the Refresh button in Chrome, and it will reload the data (As it already exists).

Now close the browser (but NOT MServer) and run the program again. It loads the header, and reports that there is one file, but the filename and filedata for the file are both empty. Where's it gone?! How can the file data be gone but the MKYDATA header and filecount are still there???

I've been trying to solve this since yesterday morning, not helped by the fact that we've had six power outages in the last 24 hours due to the crappy weather. Its doing my head in now.


GfK(Posted 2011) [#2]
Just doing more testing and can confirm I have the exact same problem on my Mac (Lion). Also tested in IE9, where SaveState does not seem to work at all.


Floyd(Posted 2011) [#3]
Wild guess, but is the saved 'state' being treated the way strings are in C/C++? If so then this string ends at the first zero character ( byte? ). This would probably be within the bytes that encode the number of files. If you are doing this little-endian style then the number of files would read back correctly, but then end of string character is next.

What I mean is suppose there is one file. You would read the MKYDATA successfully. But the file count of 1 would be encoded as characters 1 0 0 0. You could read the 1, but the next 0 signals the end of the state string.


muddy_shoes(Posted 2011) [#4]
The data is still there, it seems that it's not read in because the string is considered to be null terminated. It looks like the string read after a browser restart goes through a different code path.

You may have to work out how to store values without using a character code of 0.


GfK(Posted 2011) [#5]
You may have to work out how to store values without using a character code of 0.


Hmmm... that's not going to be possible, is it? Unless I store Ints that have been cast to strings but I don't really fancy that route. Any suggestions?

*scurries away to test*

[edit] Oh, and just to clarify, I know I shouldn't develop for HTML5 - I'm only doing so because I don't like Monk (or any of the bodged text editor alternatives) therefore I can't code and test on my Mac. That and its got the shortest build time.


muddy_shoes(Posted 2011) [#6]
Yes it's possible but less efficient than it otherwise would be. Here's a messy implementation.

    Method IntToString:String(val:Int)
        Local result:String
        result = String.FromChar($F000 | ((val Shr 20) & $0FFF) )
        result += String.FromChar($F000 | ((val Shr 8) & $0FFF))
        result += String.FromChar($F000 | (val & $00FF))
        Return result
    End
        
    Method StringToInt:Int(val:String,ind:Int)
        Return ((val[ind]&$0FFF) Shl 20) | ((val[ind+1]&$0FFF) Shl 8) |(val[ind+2]&$00FF)
    End


Just remember to change all your offsets to be three chars per integer rather than the four you were using or the two if you had changed to use my version.


GfK(Posted 2011) [#7]
So that will never store a zero anywhere? I'll give that a try.

I'm generally not very bright on this kind of stuff. Any chance you could explain how/why it works? I don't wan't to just copy/paste the code - I'd quite like to understand the logic behind it.


muddy_shoes(Posted 2011) [#8]
Okay, well the previous version split the 32-bit integer across two 16-bit char-codes (or yours above puts one byte in each of four char-codes). In order to ensure we don't have a zero char-code the new code is spreading the 32-bit integer across three char-codes and simply setting the first four spare bits of each char-code to 1 -- so even if the integer is zero, all the characters will be non-zero. The string to int process just reverses this and discards the extra bits and recombines the integer.

There's probably a smarter way to do it but it's way past my bedtime so it'll do for now.


GfK(Posted 2011) [#9]
Ahh, I see! Thanks for that.

One more thing - in your code your StringToInt() method has an index parameter. Why? Wouldn't it be just the same if you hard-coded it to read chars 0, 1 and 2 of the string? Or is there some reason you didn't do it that way?


muddy_shoes(Posted 2011) [#10]
It avoids having to slice the input string all the time. You just pass the string and the starting index.


GfK(Posted 2011) [#11]
Thanks, all working now!


GfK(Posted 2011) [#12]
Hmm.... actually it does still seem to be introducing zeros occasionally. Think it's my code, though....