Str_to_Int not working in BMax, why?

BlitzMax Forums/BlitzMax Programming/Str_to_Int not working in BMax, why?

Tibit(Posted 2005) [#1]
The exact same code is valid in B3d but in BlitzMax it get's wierd. I guess something has changed here? Can anyone figure it out? The functions are by Surreal, found them in the code archives. And they are really useful to me right now!
A = 1
B = 2

Print "A: "+A
Print "B: "+B

SA$ = IntToStr(A)
SB$ = IntToStr(B)

Print "A-String Len : "+Len(SA)
Print "B-String Len : "+Len(SB)

A = StrToInt(SA)
B = StrToInt(SB)

Print "A: "+A
Print "B: "+B


Function IntToStr$(num%, strlen% = 4)
	st$ = Chr$(num And 255)
	For shiftin = 1 To (strlen - 1)
		st$ = st$ + Chr$(num Shr (8 * shiftin))
	Next
	Return st$
End Function 

Function StrToInt%(st$)
	For shiftin = 0 To (Len (st$) - 1)
		num = num Or (Asc (Mid$ (st$, shiftin + 1, 1)) Shl shiftin * 8)
	Next
	Return num
End Function

WaitKey()



Michael Reitzenstein(Posted 2005) [#2]
Or is now logical Or only - use | for bitwise Or.


Tibit(Posted 2005) [#3]
=)
Great, it improved but it did not solve the problem.

Len,Mid and Shr is all the same.. What else can it be?



Sarge(Posted 2005) [#4]
Um i dont under stand why you are doing it this way while you have commands like

1: string.ToInt()
2: string.FromInt( strlen:int )

A = 1
B = 2

Print "A: "+A
Print "B: "+B

SA$ = IntToStr(A)
SB$ = IntToStr(B)

Print "A-String Len : "+Len(SA)
Print "B-String Len : "+Len(SB)

A = StrToInt(SA)
B = StrToInt(SB)

Print "A: "+A
Print "B: "+B

Function IntToStr$( strlen:Int )
	Return st$.FromInt( strlen:Int )
End Function 

Function StrToInt( st:String )
	Return st$.ToInt()
End Function

WaitKey()



Tibit(Posted 2005) [#5]
No that does not work, the number or int needs to be compressed into a string. Which means I don't want a function which does MyString$:+ "255". But a Function that does MyString:+ Chr(255). So the problem lies in dividing the int into ^255byte chunks and then adding them and then be able to do it all backwards to retreive the int in it's former form.

A% = 65
Text$ = Chr(A)
Len(Text) - should give 1 byte!

Text = A
Len(Text) - should give 2 bytes!

It's all about saving data.

But I don't know how to do it with Shorts, Ints or Floats.. The function I have above from B3D did this for me.


ziggy(Posted 2005) [#6]
This is not a good idea. Lots of string functions truncate data when finding a end of string character (null character).all integers from 0 to 255 have a null character in the first eight bits, so it's a little dangerous to use byte data inside strings. I recomand you to use banks (much better).
Anyway, you can always put the INT into a Bank, and read the bank into a string.


Tibit(Posted 2005) [#7]
I have never used banks, what I'm trying to do above, can it be done by simply writing to a bank and then reading from it?

Can you post a simple example?

Maybe I should add that I'm doing this in my Network Library, so I do this so I don't need to send more data than needed.

1byte Byte: 0 - 255
Uncompress: Saves as 1-3 Bytes = MaxLoss 2 bytes

2bytes Short: 0-65535
Uncompress: Saves as 1-4 Bytes = MaxLoss 3bytes

4bytes Int: -2147483648 to 2147483647
Uncompress: Saves as 1-11 Bytes = MaxLoss 7bytes

4byte float?

8byte double?

I need to pack everything into a BIGstring and send it byte by byte. And then unpack it all when it arrives.
Or is there a better way?
Because it would be a waste to send one message for each datatype and it would be a waste to send an int larger than 4bytes.


Koriolis(Posted 2005) [#8]
Maybe you should have a look at this handy functions:
http://koriolis.free.fr/forum/viewtopic.php?t=53
Look at IntToVarLenStr and VarLenStrToInt.
At worst you lose 1 byte if the integer value is *very* big.
And it doesn't suffer from the '\0' character issue.


ImaginaryHuman(Posted 2005) [#9]
I thought you could do this:

Local TheStringVariable:String=String(TheIntVariable)

or

Local TheIntVariable:Int=Int(TheStringVariable)


Koriolis(Posted 2005) [#10]
He wants to *compress* the integer, not display it.


Tibit(Posted 2005) [#11]
After doing a replace of all OR and AND to | and & it worked.

by Koriolis
at http://koriolis.free.fr/forum/viewtopic.php?t=53


Koriolis I have to say I'm Impressed! The code is public right?

I can't say I can follow the code, but I'm quite sure I can use it =)

I do have one problem with it..

Let's say someone want to send their X,Y,Dir in a package then I'll put them all into string form and then add them together PlayerData$ =IntToVarLenStr$(X)+IntToVarLenStr$(Y)+IntToVarLenStr$(Dir). Now the receiveing player have to know the size of each X,Y,Dir somehow to be able to decode it into a usable int form.

Example: if I'm at position 12,123 Dir 90 then I could send my fullupdate as a 3byte package! Impressive! But how would the receiveing player know that my X,Y,Dir are 1byte each? It seems like I have to send something like this:

PlayerData$ = IntToVarLenStr$(X)+"/"+IntToVarLenStr$(Y)+"/"+IntToVarLenStr$(Dir)

So that I can sort the values from eachother. Am I right? Do I still win data this way?

Because it is a very very convinient way to do it, but it adds uneccecery data. Perhaps some bytes +/- doesn't matter in the end.. I don't know.

Great job with the functions anyway!


Tibit(Posted 2005) [#12]
One more thing, the value depending on size is:
1-BYTE Range: -64 -> 64 Old Range: 0-255
2-BYTE Range: -8192 -> 8191 Old Range: 0-65535
3-BYTE Range: -1048576 -> 1048575
4-BYTE Range: ??? Old Range:-2147483648 to 2147483647
5-BYTE Range: ???

Calculations to determine the most efficient way:

X,Y normally within a Short 0-65535, should also work with the -8192 -> 8191 range
.
This means always 2 bytes each for X,Y,Z,Dir,Key. Total data in a normal case would be 10-bytes!

With this method X,Y,Z,Dir,Key is each 1-2byte + 1byte(the extra byte as separator). Results in 9 to 14 bytes.
Also with separators a 0 value does not need to be sent. But it's not often that is an issue anyway. Also this a very good way to send changes (delta) becuase they are usually small.

-Wait!
I can't have a separator with numbers, because one of the numbers could be represented as that separator if I have badluck. which could mess up the sent data.


Koriolis(Posted 2005) [#13]
Koriolis I have to say I'm Impressed! The code is public right?
Thanks. And yes it's public.

Because it is a very very convinient way to do it, but it adds uneccecery data. Perhaps some bytes +/- doesn't matter in the end.. I don't know.
If you read the whole thread you'll see a function that returns the length of the packed integer. It's called VarLenStrLen and returns the size of the *first* packed integer in the string. With it you do not need any separator, just concatenate every packed value, and extract them one by one on the other side (get the extracted value with VarLenStrToInt, then get the size of the packed int just extracted and trash these characters - ie keep the rightmost characters, minus the N characters just extracted -. Then continue until there is no data anymore).
In your example this means 5 to 10 bytes needed rather than 9 to 14.

Also this a very good way to send changes (delta) because they are usually small.
Yep. Generally speaking the method is efficient because integers values that a program manipulate tend to be pretty small.


Tibit(Posted 2005) [#14]
That's awesome and Brilliant!

I tested it, here is the testing code if someone would ever need it.


Now I'm back to network coding, Thanks again Koriolis!