saveGlobalData

@Simeon

This isn’t working like I expect it to. I was playing around with save and read global data and I ran into a problem. Here is an example I set up to show the problem. It looks like the string of digits (a) is treated as a number and not a string. (b) (c) and (d) are working as expected. I added the program output as a comment at the end. I expected (a) to print as 1234567890 and not 1.23457e+09 . Local and Project data also do the same thing.


function setup()
    
    a="1234567890"    -- string of digits
    b= 1234567890     -- a number
    c="a123456789"    -- string of digits with leading letter
    d="qwertyuiop"    -- string of letters
    
    saveGlobalData("a",a)
    saveGlobalData("b",b)
    saveGlobalData("c",c)
    saveGlobalData("d",d)
        
    for x,y in pairs(listGlobalData()) do
        print(x,y)
    end
     
    print()

    a=readGlobalData("a")
    print("a",a)
    
    b=readGlobalData("b")
    print("b",b)
    
    c=readGlobalData("c")
    print("c",c) 

    d=readGlobalData("d")
    print("d",d)  
       
end


--[[    Here is the output from this program

1    d
2    b
3    c
4    a

a    1.23457e+09
b    1.23457e+09
c    a123456789
d    qwertyuiop

--]]


.@dave1707 - that is interesting I hadn’t noticed this. I whipped out iExplorer and had a look at what is actually stored in the pList. For the number string you get:

<real>1234567936</real>

So the automatic cast happens when you save the data.

It’s not really a bug, this is just the way that Lua handles numbers and strings. If a string is convertible to a number, Lua will convert it.

When you read it back, you can convert it back to a string (for printing, for example) by using tostring(a).

@Simeon

If I do a print(tostring(a)) I get 1.23457e+09 printed out, not 1234567890. If that’s the case then an all numeric string can’t be saved and read back as global, local or project data. The numeric string will be shown as scientific notation unless it’s 6 digits or less, provided it doesn’t begin with zeros. If I save the string “000001” and read it back I get a 1 even if I do a tostring. If what I save isn’t what I read back then I can’t rely on that function for saving data.

Thanks for reporting this, @dave. I’ve looked into it some more and it does indeed appear to be a bug with save*Data

It asks Lua if the value is a number, before checking if it is a string. This causes Lua to attempt the conversion.

I have fixed this bug for the next version of Codea (saving a string representation of a number will keep it as a string).

@dave1707 as a temporary hack you could implement your save/load functions by adding systematically to the beginning of your strings a character (like ‘_’) when saving and removing it when you read. Of course you already know that, i said it just in case…

Removed after reading other comments.

Here is a program that will allow a string containing any values (0x00 to 0xff) to be saved in Global, Local, or Project data and read it back. The original problem with saving strings is that certain hex values would cause an error message or cause Codea to close when using the saveGlobalData etc commands. The 2 routines here (hexToAscii and asciiToHex) gets around that problem. hexToAscii will take 1 hex byte and convert it to 2 ASCII bytes. asciiToHex will take 2 ASCII bytes and convert them back to 1 hex byte. By converting 1 hex byte to 2 ASCII bytes allows you to save the string without problems. The only down side is the string being saved is twice the size of the original. When this program is run, it will show examples of the steps taken to convert the original string to ASCII, save the string, read it back, and convert it from ASCII back to the original. Slide the output pane all the way up to show more of the output. I added the command saveGlobalData(“str2”,nil) at the end to remove my example of str2 from your iPad.


function setup()   
    asciiTab={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}
    
    str1=""
    str2=""
    str3=""
    str4=""
    
    --create string str1 with values from 0 to 255 (0x00 to 0xff)
    for a = 0x00,0xff do
        str1=str1..string.char(a)
    end
    
    --show the values and length of string str1
    print("str1",string.byte(str1,1,string.len(str1)))
    print("\
str1 length",string.len(str1))
    
    --convert 1 hex byte to 2 ascii bytes
    print("\
Convert 1 hex byte (str1)\
to 2 ascii bytes (str2)")
    str2=hexToAscii(str1)
    
    --show values and length of string str2
    print("\
str2",str2)
    print("\
str2 length",string.len(str2))

    --save string str2 as global data
    print("\
saving str2 as global data")
    saveGlobalData("str2",str2)
    
    --list global data
    print("listing global data")
    for x,y in pairs(listGlobalData()) do
        print(x,y)
    end
    
    --read saved data into string str4
    print("\
read global data into str4")
    str4=readGlobalData("str2")
    
    --show values and length of string str4
    print("\
str4",str4)
    print("\
str4 length",string.len(str4))
    
    --convert 2 ascii bytes to 1 hex byte
    print("\
Convert 2 ascii bytes (str4)\
to 1 hex byte (str3)")
    str3=asciiToHex(str4)
    
    --show values and length of string str3
    print("\
str3",string.byte(str3,1,string.len(str3)))
    print("\
str3 length",string.len(str3))    

    saveGlobalData("str2",nil)   -- remove str2 from global data
        
end

function hexToAscii(in1)    --convert 1 hex byte to 2 ascii bytes
    local out1=""
    for x=1,string.len(in1) do
        z=string.byte(in1,x,x)
        a=math.floor(z/16)
        a1=asciiTab[a+1]
        b=z%16
        b1=asciiTab[b+1]
        out1=out1..a1..b1
    end
    return(out1)
end

function asciiToHex(in1)    --convert 2 ascii bytes to 1 hex byte
    local out1=""
    for x=1,string.len(in1),2 do
        a=string.sub(in1,x,x)
        a1=string.byte(a)
        if a1>57 then
            a1 = a1 - 87
        else
            a1 = a1 - 48
        end
        
        b=string.sub(in1,x+1,x+1)     
        b1=string.byte(b)   
        if b1>57 then
            b1 = b1 - 87
        else
            b1 = b1 - 48
        end
    
        z=a1*16+b1
        out1=out1..string.char(z)
    end
    return(out1)
end

function draw()
    background(40,40,50)   
end

@Simeon

when I start this program on my iPad1 , I get in print (x, y) 30 other entries from other projects. How can I delete these entries Global?

@dave1707 thanks for sharing. What i really need is the ability to save/read a table of bytes. So i have modified your code to include this functionnality. See below.

function setup()   
    asciiTab={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}
    
    str1=""
    table1={}
    table2={}
    str2=""
    str3=""
    str4=""
    
    --create string the table with values from 0 to 255 (0x00 to 0xff)
    for a = 0x00,0xff do
        table1[a]=a
    end
    
    --show the values of table1
    str1=""
    for i=0,#table1 do
        str1= str1.."-"..table1[i]
    end
    print("table1 = ",str1)
    
    --convert 1 hex byte to 2 ascii bytes
    print("\
Convert a table of bytes \
to a string in hex format")
    str2=byteTableToAsciiHex(table1)
    
    --show values and length of string str2
    print("\
str2",str2)
    print("\
str2 length",string.len(str2))

    --save string str2 as global data
    print("\
saving str2 as global data")
    saveGlobalData("str2",str2)
        
    --list global data
    print("listing global data")
    for x,y in pairs(listGlobalData()) do
        print(x,y)
    end
    
    --read saved data into string str4
    print("\
read global data into str4")
    str4=readGlobalData("str2")

    --show values and length of string str4
    print("\
str4",str4)
    print("\
str4 length",string.len(str4))
    
    --convert 2 ascii bytes to 1 hex byte
    print("\
Convert 2 ascii bytes (str4)\
to 1 hex byte (str3)")
    str3=asciiToHex(str4)

    -- convert hex string to byte table
    table2 = asciiHexToByteTable(str4)  

    -- check all the values are there
    str3=""
    for i=0,#table2 do
        str3= str3.."-"..table2[i]
    end
    print(str3)

    saveGlobalData("str2",nil)   -- remove str2 from global data
        
end

function byteTableToAsciiHex(in1)    --convert table of bytes to hex ascii string
    local out1=""
    for x=0,#in1 do
        z=x
        a=math.floor(z/16)
        a1=asciiTab[a+1]
        b=z%16
        b1=asciiTab[b+1]
        out1=out1..a1..b1
    end
    return(out1)
end

function asciiHexToByteTable(in1)    --convert 2 ascii bytes to a table of bytes
    local out1={}
    local i=0
    for x=1,string.len(in1),2 do
        a=string.sub(in1,x,x)
        a1=string.byte(a)
        if a1>57 then
            a1 = a1 - 87
        else
            a1 = a1 - 48
        end
        
        b=string.sub(in1,x+1,x+1)     
        b1=string.byte(b)   
        if b1>57 then
            b1 = b1 - 87
        else
            b1 = b1 - 48
        end
    
        z=a1*16+b1
        out1[i]=z
        i = i + 1
    end
    return(out1)
end

function hexToAscii(in1)    --convert 1 hex byte to 2 ascii bytes
    local out1=""
    for x=1,string.len(in1) do
        z=string.byte(in1,x,x)
        a=math.floor(z/16)
        a1=asciiTab[a+1]
        b=z%16
        b1=asciiTab[b+1]
        out1=out1..a1..b1
    end
    return(out1)
end

function asciiToHex(in1)    --convert 2 ascii bytes to 1 hex byte
    local out1=""
    for x=1,string.len(in1),2 do
        a=string.sub(in1,x,x)
        a1=string.byte(a)
        if a1>57 then
            a1 = a1 - 87
        else
            a1 = a1 - 48
        end
        
        b=string.sub(in1,x+1,x+1)     
        b1=string.byte(b)   
        if b1>57 then
            b1 = b1 - 87
        else
            b1 = b1 - 48
        end
    
        z=a1*16+b1
        out1=out1..string.char(z)
    end
    return(out1)
end

function draw()
    background(40,40,50)   
end

@Jmv30

when I start your codeon my iPad 1, I get following output:

saving str2 as global data
listing global data
1 Aquarius
2 car1
3 1-Capricorn
4 c
5 SpritelyKeys
6 Spritely24
7 d
8 b
9 1-Aries
10 Libra
11 1-Leo
12 str2
13 Wing
14 Ampel
15 Pisces
16 1-Cancer
17 1-Sagittarius
18 1-Libra
19 Spritely2
20 1-Scorpio
21 B0
22 Spritely18
23 Capricorn
24 1-Aquarius
25 1-Pisces
26 Scorpio
27 1-Gemini
28 1-Virgo
29 scorpio
30 1-Taurus
31 0
32 globalDataKey
33 Sagittarius
34 a
35 Copy of Spritely2

what can I do to clean GlobalData?

By the way, there’s a family of tools for manipulating binary, decimal, and hexadecimal data in lua that can be easily found on the internet. I added octal and put it in my library which is at http://www.math.ntnu.no/~stacey/code/CodeaLibrary

.@matox - you can use my simple file manager class to manually delete items in global data (and local and project data). Use with care though - there is no undo! http://codeatuts.blogspot.com.au/2012/09/tutorial-17-simple-file-manager-for.html

@Reefwing
Thanks for help. But I got errors - Nil bei Version -
So I have stored all my Code in Notizen and then delete Codea and load it again.
Now globalData is clean

Two questions 1 what is the point in having table.concat if you can’t use it to convert a table and all its values into a string?

-AND-

2 where is the extended documentation on how to use it in conjunction with saveGlobalData?

@pioyugb

Here are 2 examples of table.concat . Can’t help with question 2.


function setup()
    tab={1,"one",2,"two",3,"three",4,"four",5,"five"}
    
    str=table.concat(tab,"*")  -- put an * between all entries
    print(str)
    
    print()
    
    str=table.concat(tab,"\
")  -- put a carriage return between all entries
    print(str)
end

function draw()
    background(40, 40, 50)
end