Union
Re: Union
I think you need string * 9 and not zstring * 9 to make it work as expected.
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
Very weirdly, if I change zstring*9 by string*9 everywhere, I don't have any more the issue with the array boundary (I can go beyond 2^16 - 1).dodicat wrote:I think you need string * 9 and not zstring * 9 to make it work as expected.
But I loose all the compression advantage:
With strings:
Code: Select all
memory usage
32760
36855 '!!
get the value at index 111 back
**** o
**** 0
111
get the value at index 1024 back
**** 1024
**** 1024
1024
Code: Select all
memory usage
32760
7962 '<------ good
get the value at index 111 back
**** o
**** 0
111
get the value at index 1024 back
**** 1024
**** 1024
1024
Edit:
Ahah! It is needed to use string*9 within the UNION, but not in the rest of the code. Then it works again... Thanks :)
I still wonder the reason under the hood. The fact that Union are said not to be quite tolerante to strings (the not fixed-len ones) it tends to lead to use zstrings rather... Silly, but true. Anyway, where the difference comes from when it is all about fixed-len stuff here?
Code: Select all
dim as uinteger n => 18 'size of the 2 arrays used below 2^n -1
dim as uinteger upper => 2^n - 1
union SPACESAVER
as uinteger value
as string*9 zstr
as ubyte firstbyte
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
declare function ConsistencyCheck(byval as uinteger) as boolean
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
select case THIS.firstbyte
case 0
return str(V)
case else
return THIS.zstr
end select
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
THIS.zstr = Z
? "****", Z
?"****", cUint(Z)
select case ( (cUint(Z)<>0) andAlso (cUint(Z) mod 256 = 0))
case TRUE
return val(Z)
case else
return THIS.value
end select
end function
function SPACESAVER.ConsistencyCheck(byval ArrayIndex as uinteger) as boolean
if not THIS.SetStringGetValue(THIS.SetValueGetString(ArrayIndex))=ArrayIndex then
return FALSE
else
return TRUE
end if
end function
dim as SPACESAVER spsa
redim as uinteger arrayOfUInt(1 to upper)
redim as zstring*9 arrayOfStr(1 to upper)
dim as uinteger sumUintArray
dim as uinteger sumStrArray
for i as integer = 1 to upper
arrayOfUInt(i) = i
arrayOfStr(i) = spsa.SetValueGetString( arrayOfUInt(i) )
sumUintArray += len(i)
sumStrArray += len( arrayOfStr(i) )
next i
? "memory usage"
? sumUintArray
? sumStrArray
? "get the value at index 111 back"
? spsa.SetStringGetValue( arrayOfStr(111) )
? "get the value at index 1024 back"
? spsa.SetStringGetValue( arrayOfStr(1024) )
getKey()
Code: Select all
memory usage
2097144
722001
get the value at index 111 back
**** o
**** 0
111
get the value at index 1024 back
**** 1024
**** 1024
1024
Re: Union
When writing a number, all bytes of number are updated.
When writing a zstring, only the useful characters (plus the terminal character) are updated (the followings are unchanged).
(for a 'string * n', all characters are always updated)
Simple workaround to your original code:
Note: if you use a fix-len string, a 'string * 8' is sufficient.
When writing a zstring, only the useful characters (plus the terminal character) are updated (the followings are unchanged).
(for a 'string * n', all characters are always updated)
Simple workaround to your original code:
Code: Select all
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
THIS.value = 0 '' in order to reset the zstring
THIS.zstr = Z
? "****", Z
?"****", cUint(Z)
select case ( (cUint(Z)<>0) andAlso (cUint(Z) mod 256 = 0))
case TRUE
return val(Z)
case else
return THIS.value
end select
end function
Re: Union
You have not solved everything.fxm wrote:As soon as a theuintegerlongint contains a not higher null ubyte, that no longer works.
Simple example:
spsa.value = 256
As soon as the number contains any significant ubyte equal to zero, it no longer works.
For example, try the value: &h010001 or &h01000101 ...
Re: Union
KeyPgUnion → fxm [Rewording]
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
There is a lot to master in the above answers. I start from the simplest thing to my ears. How the Union buffer is filled and cleaned.fxm wrote: Simple workaround to your original code:Note: if you use a fix-len string, a 'string * 8' is sufficient.Code: Select all
THIS.value = 0 '' in order to reset the zstring
I've made this code to summarize a little:
Code: Select all
union US
declare sub PrintContent()
as zstring*9 zs
as uinteger<8*8> u
as uinteger<8*1> v
as string*8 s
type
as ubyte b1 : as ubyte b2
as ubyte b3 : as ubyte b4
as ubyte b5 : as ubyte b6
as ubyte b7 : as ubyte b8
end type
end union
sub US.PrintContent()
? "zString9=",, THIS.zs
? "value=",, THIS.u
? "1 byte value=",, THIS.v
? "string8=",,THIS.s
? ,, "________"
? THIS.b1; ":"; : ? THIS.b2; ":";
? THIS.b3; ":"; : ? THIS.b4; ":";
? THIS.b5; ":"; : ? THIS.b6; ":";
? THIS.b7; ":"; : ? THIS.b8
end sub
dim as US uuss
? "fill the buffer"
uuss.u = &h1111111111111111
uuss.PrintContent()
?
? "after a zstring assignement, things are not cleaned up enough"
uuss.zs = "hhhhh"
uuss.PrintContent()
?
? "after a string assignement it's ok"
uuss.s = "hhhhh"
uuss.PrintContent()
?
? "fill the buffer again"
uuss.u = &h1111111111111111
uuss.PrintContent()
?
? "after a 8bits (1 byte) value assignement it's not cleaned up"
uuss.v = &h44
uuss.PrintContent()
?
? "after a 64bits (8 bytes) value assignement it seems OK"
uuss.u = &h44
uuss.PrintContent()
getKey()
Better seen with a pic:running: OS:WINDOWS FBC_Version =1.06.0 64bit
fill the buffer
zString9= ????????
value= 1229782938247303441
1 byte value= 17
string8= ????????
________
17:17:17:17:17:17:17:17
after a zstring assignement, things are not cleaned up enough
zString9= hhhhh
value= 1229764621677127784
1 byte value= 104
string8= hhhhh
________
104:104:104:104:104:0:17:17
after a string assignement it's ok
zString9= hhhhh
value= 448428271720
1 byte value= 104
string8= hhhhh
________
104:104:104:104:104:0:0:0
fill the buffer again
zString9= ????????
value= 1229782938247303441
1 byte value= 17
string8= ????????
________
17:17:17:17:17:17:17:17
after a 8bits (1 byte) value assignement it's not cleaned up
zString9= D???????
value= 1229782938247303492
1 byte value= 68
string8= D???????
________
68:17:17:17:17:17:17:17
after a 64bits (8 bytes) value assignement it seems OK
zString9= D
value= 68
1 byte value= 68
string8= D
________
68:0:0:0:0:0:0:0
I still don't get very well the other affair with zstrings and significant stuff or null terminator...fxm wrote: As soon as the number contains any significant ubyte equal to zero, it no longer works.
For example, try the value: &h010001 or &h01000101 ...
Re: Union
Values in hexadecimal, thus broken down by byte:fxm wrote:As soon as the number contains any significant ubyte equal to zero, it no longer works.
For example, try the value: &h010001 or &h01000101 ...
Code: Select all
&h|01|00|01|
^null byte (terminal character for a zstring)
&h|01|00|01|01|
^null byte (terminal character for a zstring)
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
Ok I think I get it. Each time a ASCII character is written (corresponding to a ubyte say) -> if it is a null value, that's a problem for zstrings that will break down right there. So we'll have to watch each Bytes, and reject the conversion to zstring if there is a null byte around. I think it's quite feasible fortunately!!fxm wrote: Values in hexadecimal, thus broken down by byte:Code: Select all
&h|01|00|01| ^null byte (terminal character for a zstring) &h|01|00|01|01| ^null byte (terminal character for a zstring)
edit:
First, to go back to the fundation:
Code: Select all
union SPACESAVER
as uinteger<8*8> value
as string*8 strng
type
as ubyte b1, b2, b3, b4, b5, b6, b7, b8
end type
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
return THIS.strng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
THIS.strng = Z
return THIS.value
end function
dim as SPACESAVER spsa
scope
dim as uinteger<64> ui = &h11223344
? "numeric value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
?
end scope
scope
dim as uinteger<64> ui = &h11220044
? "numeric value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
?
end scope
scope
dim as uinteger<64> ui = &h11003344
? "numeric value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
?
end scope
scope
dim as uinteger<64> ui = &h110033005566
? "numeric value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
?
end scope
getKey()
numeric value: 11223344
after 1 switch: 11223344
array of byte: 443322110000
string stored: D3"◄
numeric value: 11220044
after 1 switch: 44
array of byte: 440000000
string stored: D
numeric value: 11003344
after 1 switch: 3344
array of byte: 4433000000
string stored: D3
numeric value: 110033005566
after 1 switch: 5566
array of byte: 6655000000
string stored: fU
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
Hi all,
@fxm, I've finally crafted this union below. This seems to be working after writting some tedious nested if test to avoid the null bytes that the strings seem unable to store well enough for the job asked.
Could you tell me if you see something I missed? Or anyone who have some time for this?
From my side my tests look successull.
@fxm, I've finally crafted this union below. This seems to be working after writting some tedious nested if test to avoid the null bytes that the strings seem unable to store well enough for the job asked.
Could you tell me if you see something I missed? Or anyone who have some time for this?
From my side my tests look successull.
Code: Select all
union SPACESAVER
as uinteger<8*8> value
as string*18 strng 'can't be exchanged outside if null char inside
as zstring*19 zstrng 'will be truncated immediatly if null char inside
type
as ubyte b1, b2, b3, b4, b5, b6, b7, b8
end type
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
if .b8=0 then
if .b7=0 then
if .b6=0 then
if .b5=0 then
if .b4=0 then
if .b3=0 then
if .b2=0 then
if .b1=0 then
return str(.value)
end if
end if
else
if .b2*.b1=0 then
return str(.value)
end if
end if
else
if .b3*.b2*.b1=0 then
return str(.value)
end if
end if
else
if .b4*.b3*.b2*.b1=0 then
return str(.value)
end if
end if
else
if .b5*.b4*.b3*.b2*.b1=0 then
return str(.value)
end if
end if
else
if .b6*.b5*.b4*.b3*.b2*.b1=0 then
return str(.value)
end if
end if
else
if .b7*.b6*.b5*.b4*.b3*.b2*.b1=0 then
return str(.value)
end if
end if
end with
'if no null bytes let the union do the job
return THIS.strng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
if (str(val(Z))=Z) then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function
dim as SPACESAVER spsa
scope
dim as uinteger<64> ui = &h11223344
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11220044
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11003344
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11000099000066
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "array of byte:",
? hex(spsa.b1); hex(spsa.b2); hex(spsa.b3); hex(spsa.b4); hex(spsa.b5); hex(spsa.b6); hex(spsa.b7); hex(spsa.b8)
? "string stored:", spsa.strng
? "zstring stored:", spsa.zstrng
var temp = spsa.strng
spsa.value = 0
? "back to initial:", spsa.SetStringGetValue(temp)
?
end scope
getKey()
numeric value: 287454020
hex. num. value: 11223344
after 1 switch: 11223344
array of byte: 443322110000
string stored: D3"◄
zstring stored: D3"◄
back to initial: 287454020
numeric value: 287440964
hex. num. value: 11220044
after 1 switch: 11220044
array of byte: 3238373434303936
string stored: 287440964
zstring stored: 287440964
back to initial: 287440964
numeric value: 285225796
hex. num. value: 11003344
after 1 switch: 11003344
array of byte: 3238353232353739
string stored: 285225796
zstring stored: 285225796
back to initial: 285225796
numeric value: 4785077170995302
hex. num. value: 11000099000066
after 1 switch: 11000099000066
array of byte: 3437383530373731
string stored: 4785077170995302
zstring stored: 4785077170995302
back to initial: 4785077170995302
Re: Union
My version (raw code, little tested):
Code: Select all
union SPACESAVER
as uinteger<8*8> value
as zstring*(20+1) zstrng 'UINTEGER 64bit: max=18446744073709551615
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
for i as integer = 7 to 1 step -1
if .zstrng[i] <> 0 then
for j as integer = i-1 to 0 step -1
if .zstrng[j] = 0 then
return str(.value)
end if
next j
end if
next i
end with
'if no null bytes let the union do the job
return THIS.zstrng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
if (str(val(Z))=Z) then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function
dim as SPACESAVER spsa
scope
dim as uinteger<64> ui = &h11223344
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11220044
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11003344
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = &h11000099000066
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
getKey()
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
I've launched a first test with an array of 10000 values (1 to 10000) and I found some errors (for value = 48 to 57):fxm wrote:My version (raw code, little tested):Code: Select all
(I added a useless THIS.value=0 at line 25, it doesn't cause the error here)
8 * 10000 = 80000
size of the array data 19820
problem here string stored=0 initial value= 48
problem here string stored=1 initial value= 49
problem here string stored=2 initial value= 50
problem here string stored=3 initial value= 51
problem here string stored=4 initial value= 52
problem here string stored=5 initial value= 53
problem here string stored=6 initial value= 54
problem here string stored=7 initial value= 55
problem here string stored=8 initial value= 56
problem here string stored=9 initial value= 57
numeric value: 47
hex. num. value: 2F
after 1 switch: 2F
zstring stored: /
back to initial: 47
numeric value: 48
hex. num. value: 30
after 1 switch: 0
zstring stored: 0
back to initial: 0
end
Code: Select all
union SPACESAVER
as uinteger<8*8> value
as zstring*(20+1) zstrng 'UINTEGER 64bit: max=18446744073709551615
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
for i as integer = 7 to 1 step -1
if .zstrng[i] <> 0 then
for j as integer = i-1 to 0 step -1
if .zstrng[j] = 0 then
return str(.value)
end if
next j
end if
next i
end with
'if no null bytes let the union do the job
return THIS.zstrng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
THIS.value = 0
if (str(val(Z))=Z) then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function
dim as SPACESAVER spsa
dim as integer sumlen
dim as string strarray(1 to 10000)
for i as integer = 1 to 10000
strarray(i) = spsa.SetValueGetString(i)
sumlen += len(strarray(i))
next i
? "8 * 10000 =", 8 * 10000
? "size of the array data", sumlen
for i as integer = 1 to 10000
dim as SPACESAVER spsa1
if spsa1.SetStringGetValue(strarray(i))<>i then
? "problem here", "string stored=";strarray(i), "initial value=";i
end if
next i
scope
dim as uinteger<64> ui = 47
?
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
scope
dim as uinteger<64> ui = 48
?
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
? "back to initial:", spsa.SetStringGetValue(spsa.zstrng)
?
end scope
? "end"
getKey()
Same test with my code gives more errors (including those cited above):
[Edit]8 * 10000 = 80000
size of the array data 19667
problem here string stored=0 initial value= 48
problem here string stored=1 initial value= 49
problem here string stored=2 initial value= 50
problem here string stored=3 initial value= 51
problem here string stored=4 initial value= 52
problem here string stored=5 initial value= 53
problem here string stored=6 initial value= 54
problem here string stored=7 initial value= 55
problem here string stored=8 initial value= 56
problem here string stored=9 initial value= 57
problem here string stored= initial value= 256
problem here string stored= initial value= 512
problem here string stored= initial value= 768
problem here string stored= initial value= 1024
problem here string stored= initial value= 1280
problem here string stored= initial value= 1536
problem here string stored= initial value= 1792
problem here string stored= initial value= 2048
problem here string stored= initial value= 2304
problem here string stored= initial value= 2560
problem here string stored= initial value= 2816
....
Last edited by Tourist Trap on Dec 12, 2018 22:21, edited 1 time in total.
Re: Union
Code: Select all
union SPACESAVER
as uinteger<8*8> value
type
as zstring*20+1 zstrng 'UINTEGER 64bit: max=18446744073709551615
as byte flag
end type
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
for i as integer = 7 to 1 step -1
if .zstrng[i] <> 0 then
for j as integer = i-1 to 0 step -1
if .zstrng[j] = 0 then
.flag = 1
return str(.value)
end if
next j
end if
next i
end with
'if no null bytes let the union do the job
THIS.flag = 0
return THIS.zstrng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
if THIS.flag=1 then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Union
It works!fxm wrote:Code: Select all
Still remaining a little issue. When I run the array test, the value returned via the function string->tovalue doesn't give the right stuff. Even if the right string is there. It's a small issue I guess.
Code: Select all
union SPACESAVER
as uinteger<8*8> value
type
as zstring*20+1 zstrng 'UINTEGER 64bit: max=18446744073709551615
as byte flag
end type
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
for i as integer = 7 to 1 step -1
if .zstrng[i] <> 0 then
for j as integer = i-1 to 0 step -1
if .zstrng[j] = 0 then
.flag = 1
return str(.value)
end if
next j
end if
next i
end with
'if no null bytes let the union do the job
THIS.flag = 0
return THIS.zstrng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
if THIS.flag=1 then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function
'------------------------------------------------------test1
dim as SPACESAVER spsa
scope
dim as uinteger<64> ui = 256
?
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
var temp = spsa.zstrng
spsa.value = 0
? "back to initial:", spsa.SetStringGetValue(temp)
?
end scope
scope
dim as uinteger<64> ui = 2560
?
? "numeric value:", ui
? "hex. num. value:", hex(ui)
? "after 1 switch:", hex(spsa.SetStringGetValue(spsa.SetValueGetString( ui )))
? "zstring stored:", spsa.zstrng
var temp = spsa.zstrng
spsa.value = 0
? "back to initial:", spsa.SetStringGetValue(temp)
?
end scope
'------------------------------------------------------test2
dim as integer sumlen
redim as string strarray(1 to 2^12)
for i as integer = 1 to 2^12
strarray(i) = spsa.SetValueGetString(i)
sumlen += len(strarray(i))
next i
? "array data consummed", sumlen
for i as integer = 1 to 2^12
dim as SPACESAVER spsa2
spsa2.value = 0
if spsa2.SetStringGetValue(strarray(i))<>i then
? "problem here", "string stored=";strarray(i);",";spsa2.SetStringGetValue(strarray(i)), "initial value=";i
end if
next i
? "end"
getKey()
Do you think there is a way to get a simpler solution always with this kind of union?numeric value: 2560
hex. num. value: A00
after 1 switch: A00
zstring stored: 2560
back to initial: 2560
array data consummed 7966
problem here string stored=256,3552562 initial value= 256
problem here string stored=512,3289397 initial value= 512
problem here string stored=768,3683895 initial value= 768
problem here string stored=1024,875704369 initial value= 1024
problem here string stored=1280,808989233 initial value= 1280
problem here string stored=1536,909325617 initial value= 1536
problem here string stored=1792,842610481 initial value= 1792
problem here string stored=2048,942944306 initial value= 2048
problem here string stored=2304,875574066 initial value= 2304
problem here string stored=2560,808858930 initial value= 2560
problem here string stored=2816,909195314 initial value= 2816
problem here string stored=3072,842477619 initial value= 3072
problem here string stored=3328,942814003 initial value= 3328
problem here string stored=3584,876098867 initial value= 3584
problem here string stored=3840,808728627 initial value= 3840
problem here string stored=4096,909717556 initial value= 4096
end
Is your flag stored at the last character (n°21) of the zstring*21 (due maybe to reverse order of strings in memory?) or I 'm wrong?
Re: Union
'zstrng' and 'flag' are in a Type block, so there is no common memory between them.
'flag' is declared after 'zstrng', so no common memory with 'value'.
'flag' is declared after 'zstrng', so no common memory with 'value'.
Re: Union
Last attempt for me (this strange and twisted use of Union is not very exciting):
Code: Select all
union SPACESAVER
as uinteger<8*8> value
type
as zstring*20+1 zstrng 'UINTEGER 64bit: max=18446744073709551615
as byte flag
end type
declare function SetValueGetString(byval as uinteger) as string
declare function SetStringGetValue(byref as const string) as uinteger
end union
function SPACESAVER.SetValueGetString(byval V as uinteger) as string
THIS.value = V
'test for null bytes
with THIS
for i as integer = 7 to 1 step -1
if .zstrng[i] <> 0 then
for j as integer = i-1 to 0 step -1
if .zstrng[j] = 0 then
.flag = 1
return str(.value)
end if
next j
end if
next i
end with
'if no null bytes let the union do the job
THIS.flag = 0
return THIS.zstrng
end function
function SPACESAVER.SetStringGetValue(byref Z as const string) as uinteger
dim as SPACESAVER ss
ss.SetValueGetString(valuint(Z))
if ss.flag=1 or THIS.flag=1 then
THIS.zstrng = Z
return val(Z)
else
THIS.zstrng = Z
return THIS.value
end if
end function