Need help with BYTES
BlitzMax Forums/BlitzMax Programming/Need help with BYTES
| ||
Hi, ive been going nuts. I hope someone can help me get this awnsers. (some of the awnsers i know already, but i ask anyway, just in case im doing somethign wrong, i find out) 1) How do i create a Byte array 2) How do i append another Byte array to one 3) How do i pick 1 or more bytes from a byte array 4) How do i resize a byte array (e.g. remove the first bytes) Basicly, we all know the commands LEFT$, MID$, RIGHT$, etc... for string manipulation. And we know arrays. Now all i need is be able todo this on byte level. But actualy, i also need to be able to read Shorts, and Ints. But if needed i write my own class. I know off the TBank, but im not sure how you van do point 1 to 4 with a TBank. So thats why i tought i need it as an array. Basicly, what i want todo is, read the buffer of a SocketStream (entirely) and then append the new data, to the old data, that was saved in the buffer of the class. As this buffer grows and grows, another method would check for packets and cut them out one by one. Thanks for helping! |
| ||
1)Local mybytes:byte[200] 2) Local mybytes:byte[200] Local myotherbytes:byte[100] Local allmybytes:byte[] = mybytes + myotherbytes 3) Local mybytes:byte[200] Local abyte:byte = mybytes[15] 4) Local mybytes:byte[200] Print mybytes.length mybytes = mybytes[5..] Print mybytes.length not really tested... :-p |
| ||
4) If you want to resize your array dynamically, remember that resizing is slow. |
| ||
Ok, i have yet another problem, that is, having the bytes, i cant do anything with them, as it gives type errors. Any ideas how to make this work? I dont specificly need a bytearray, but i want to be able todo the logic as follows. SuperStrict Graphics 640, 480 Local client:OClient = OClient.Create("127.0.0.1", 6121) While Not KeyHit(KEY_ESCAPE) client.onRecieve() Wend Rem Function ToString(bytes:Byte[]) Local str:String Local char:String Local i:Int = 0 While char = Chr(bytes[i..i+1]) str = str + char i = i + 1 Wend Return str End Function EndRem Type OClient Field host:String Field port:Int Field socket:TSocket Field stream:TSocketstream Field buffer:TBytes Function Create:OClient(host:String, port:Int) Local client:OClient = New OClient client.host = host client.port = port client.socket = CreateTCPSocket() ConnectSocket(client.socket, HostIp(host), port) If client Then client.stream = CreateSocketStream(client.socket) Return client Else Return Null End If End Function Method onPacketReceive(packetType:Byte, packetData:Byte[]) Print "Received packet type: " + packetType + " with data: " + packetData[..SizeOf(packetData)] End Method Method onRecieve() If SocketReadAvail(Self.socket) > 0 Self.buffer.Append(Self._ReadBytes()) Local size:Int = SizeOf(Self.buffer.bytes) If size > 3 Then packetSize = Self.buffer.ReadShort(1) If size - 3 >= packetSize Then packetType = Self.buffer.ReadByte(0) packetData = Self.buffer.ReadBytes(3, packetSize) Self.buffer.Pop(size) Self.onPacketReceive(packetType, packetData) End If End If End If End Method Method _ReadBytes() Local bytes:Byte[] While SocketReadAvail(Self.socket) > 0 bytes = bytes + ReadByte(Self.stream) Wend Return bytes End Method End Type Type TBytes Field bytes:Byte[] Method Write(bytes:Byte) Self.bytes = bytes End Method Method Append(bytes:Byte) Self.bytes = Self.bytes + bytes End Method Method Pop(length:Int) Self.bytes = Self.bytes[length..(SizeOf(Self.bytes)-length)] End Method Method Read() Return Self.bytes End Method Method ReadBytes:Byte(offset:Int, length:Int) Return Self.bytes[offset..(offset+length)] End Method Method ReadByte:Byte(offset:Int) Return Self.bytes[offset..(offset+1)] End Method Method ReadShort:Short(offset:Int) Return Self.bytes[offset..(offset+2)] End Method Method ReadInt:Int(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadLong:Long(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadFloat:Float(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadDouble:Double(offset:Int) Return Self.bytes[offset..(offset+8)] End Method End Type |
| ||
first understand that a string and an array can not be used the same way. you can not print an array of bytes and a string the same way or read them the same way. Arrays of bytes have to be read or printed one byte at a time unlike strings. You can access each byte of the string through the corresponding index and print its "byte value". if you want to see the actual character you have to convert the byte to a char such as: name:string = "Jesse" print name[0] print chr(name[0]) this will print 74 and the letter "J" with this in mind I have somewhat fixed your code to work first with bytes: and then with strings: As you can see the one with string is a lot simpler but only because it is done by the compiler, unlike the one with bytes that everything has to be coded. note that I have not tested so there might be some logic errors. [edited] look at this code: http://www.blitzmax.com/Community/posts.php?topic=81750#921145 In principle it does the same thing but with tbanks and is alot simpler |
| ||
I would add that BlitzMax strings are 2 bytes strings due to unicode. so be careful! |
| ||
and String.FromBytes(bytearray, size) is sometimes useful too :-) |
| ||
and String.FromBytes(bytearray, size) is sometimes useful too :-) lol, just learned something new :-). stuff I constatly see but ignore. |
| ||
AH! thats it, i knew it was something like Brucey, i did this back in feb. this year ,but i forgot. I was playign with CString()... but it was FromBytes() Great. Also, to get an INT from a byte, how does that work? if i just put a byte in an INT it will give a type error. If i make it a string, it will convert to a charcter. I need to be able to get the byte number. Since i store values between 0-255 in bytes. :) |
| ||
To get an Int, you need to do something like :' if you have a byte array Print Int Ptr(Byte Ptr(bytes) + offset)[0] ' if you have a byte ptr Int Ptr(byteptr + offset)[0] Which should return you the contents of the 4 bytes from offset. You can make a Byte Ptr from a Byte Array with Local byteptr:Byte Ptr = bytes |
| ||
thanks! |
| ||
ugh... im sorry for not managing this on my own but its nasty. i have fixed the code and did some other work on it, yet i still keep getting errors in SuperStrict, i just cant figure how to solve the last type issues. SuperStrict Graphics 640, 480 Local client:OClient = OClient.Create("127.0.0.1", 6121) If Not client Then End While Not KeyHit(KEY_ESCAPE) 'If KeyHit(KEY_SPACE) Then client.Send("Test") client.onRecieve() Wend Type OClient Field host:String Field port:Int Field socket:TSocket Field stream:TSocketstream Field buffer:TBytes Function Create:OClient(host:String, port:Int) Local client:OClient = New OClient client.host = host client.port = port client.socket = CreateTCPSocket() ConnectSocket(client.socket, HostIp(host), port) If client Then client.stream = CreateSocketStream(client.socket) Return client Else Return Null End If End Function Method onPacketReceive(packetType:Byte, packetData:Byte[]) Print "Received packet type: " + String(Int Ptr(packetType)[0]) + " with data: " String.FromBytes(packetData, SizeOf(packetData)) End Method Method onRecieve() If SocketReadAvail(Self.socket) > 0 While SocketReadAvail(Self.socket) > 0 Self.buffer.Append(ReadByte(Self.stream)) Wend Local size:Int = SizeOf(Self.buffer.bytes) If size > 3 Then Local packetSize:Short = Self.buffer.ReadShort(1) If size - 3 >= packetSize Then Local packetType:Byte = Self.buffer.ReadByte(0) Local packetData:Byte[] = Self.buffer.ReadBytes(3, packetSize) Self.buffer.Pop(size) Self.onPacketReceive(packetType, packetData) End If End If End If End Method End Type Type TBytes Field bytes:Byte[] Method Set(bytes:Byte[]) Self.bytes = bytes End Method Method Append(bytes:Byte) Self.bytes[Self.bytes.length] = bytes End Method Method Pop(length:Int) Self.bytes = Self.bytes[length..(SizeOf(Self.bytes)-length)] End Method Method Get:Byte[]() Return Self.bytes End Method Method ReadBytes:Byte[](offset:Int, length:Int) Return Self.bytes[offset..(offset+length)] End Method Method ReadByte:Byte(offset:Int) Return Self.bytes[offset..(offset+1)] End Method Method ReadShort:Short(offset:Int) Return Self.bytes[offset..(offset+2)] End Method Method ReadInt:Int(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadLong:Long(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadFloat:Float(offset:Int) Return Self.bytes[offset..(offset+4)] End Method Method ReadDouble:Double(offset:Int) Return Self.bytes[offset..(offset+8)] End Method End Type Isnt there a way todo this without ByteArray maybe? What would be faster? I have no idea! Would a TBank work fast enough?... cant i make a MemmoryStream or something? that i would just append from the TCP stream to the Buffer stream, and pop the packets off when they arrived 100%. |
| ||
You're returning a byte array but declared a byte. You either need to extract the byte you want to return or change the return to byte[]. |
| ||
Method Append(bytes:Byte) Self.bytes[Self.bytes.length] = bytes End Method what? |
| ||
Heh :-) I think he meant : Method Append(bytes:Byte[]) Self.bytes :+ bytes End Method |
| ||
I guess I shouldn't post in this thread anymore. I know when I am being ignored. Neither your suggestions or mine are being used. thi is your suggestion: ' if you have a byte array Print Int Ptr(Byte Ptr(bytes) + offset)[0] ' if you have a byte ptr Int Ptr(byteptr + offset)[0] and this is what he did: Method ReadInt:Int(offset:Int) Return Self.bytes[offset..(offset+4)] End Method |
| ||
I'm guessing part of the problem is a lack of understanding of all this ptr nonsense. Some of it can take a while to get ones head around. and this is what he did Not entirely fair, as it looks like that is his original effort, which he hasn't actually changed yet. Some of these functions would probably be easier with a Bank, rather than a byte array - as least code wise, since Bank has most of this functionality already. No Pop or append though - excepting for the Resize method. What would be faster? I have no idea! Would a TBank work fast enough? Probably about the same speed, I'd guess. At least not noticeably different. If you want to stick to byte[], I suggest adding an extra field : Field bytePtr:Byte Ptr which you align with your array - makes the rest of your code tidier. Method Set(bytes:Byte[]) Self.bytes = bytes bytePtr = Self.bytes End Method and so on for each method which requires a new byte[] object : Append and Pop. And subsequently this method : Method ReadInt:Int(offset:Int) Return Self.bytes[offset..(offset+4)] End Method could be changed to Method ReadInt:Int(offset:Int) Return Int Ptr(bytePtr + offset)[0] End Method ... and so on for the others. |
| ||
Not entirely fair, as it looks like that is his original effort, which he hasn't actually changed yet. I guess. So, excuse my impatience. :-) |