Xcode (Cocoa) how to write byte to NSData - cocoa-touch

Xcode...
I want to write one byte (1) to NSData. It seems very simple but im not able to find the proper link how to do it. I try to do that using unsigned char. But that stores the hex value.

You cannot add bytes to NSData use NSMutableData appendBytes:bytes length: method

Related

NSString value as NSData output

I have a NSString which is #"15".
I want my NSData to be 15 also. I know how to convert it to get the value 31 35 but I would like my NSData to be 15 if I use NSLog on it. I'm not asking for a conversion but more for a translation. I don't wanna change the NSLog print but the NSData value. Is there anyway to do it ?
Parse the string to an integer (lets assume a signed 32-bit integer):
NSString *str = #"15";
int32_t i = (int32_t)[str intValue];
To encode it in native endian:
NSData *data = [NSData dataWithBytes:&i length:sizeof(i)];
Note: if you intend to transmit that data to another computer then you need to decide on a common endianness of primitive types. Big endian is traditionally used and facilitated with functions like htonl(), ntohl(), etc. If the computers are all the same platform then you can use the native endianness, for a slight performance boost and code simplification.
You need to convert the string to a byte first (by parsing it). Then you can build the NSData from the byte.

Convert NSValue to NSData and back again, with the correct type

I would like to be able to convert an objective-c object, such as an NSArray or UIImage into an NSData object, which I can then use to write to disk. I first converted them to an NSValue, which I then planned on converting to NSData. This question provided part of the answer, but as they were working with NSNumber, they didn't really have a need to convert it back to NSValue.
I have seen other questions such as this one that relies on NSKeyedArchiver, but I would like to steer away from this due to the vast size inflation that occurs.
Therefore my code at the moment for encoding an NSData object from an NSValue, from the first question, is as follows:
+(NSData*) dataWithValue:(NSValue*)value {
NSUInteger size;
const char* encoding = [value objCType];
NSGetSizeAndAlignment(encoding, &size, NULL);
void* ptr = malloc(size);
[value getValue:ptr];
NSData* data = [NSData dataWithBytes:ptr length:size];
free(ptr);
return data;
}
My question is how would I go about decoding an NSData object that has been encoded in this manner and get back the original objCType from the NSValue?
I would assume I would be using something along these lines
[NSValue valueWithBytes:[data bytes] objCType:typeHere];
How would I get back the type information?
Use NSKeyedArchiver to save the items and NSKeyedUnarchiver to restore the object. The object must conform to NSCoding and in the case of a collection all contained items must also conform to NSCoding.
See the Apple documentation of NSKeyedArchiver and NSCoder
Your approach will only work for primitive types (int, float, structs without pointers, ...) inside your NSValue. Otherwise you will only get the meaningless pointer value but not the actual data in your NSData object.
To also pass the actual type string along you would have to figure out a way to get this inside your NSData object as well. Not impossible, but it will not solve your actual problem.
Using a keyed archiver as zaph suggests is much better.

Sending packets to Minecraft server: Objective c

I've been trying to send packets to a minecraft server from my custom Cocoa application (written in objective-c of course). I am a little confused as how to do that though. I did it in Java. That was very easy. Doing this is objective-c though is proving to be a bit more challenging.
This is the code that I am using:
- (void)handshake
{
PacketHandshake *packet = [PacketHandshake packetString:[NSString stringWithFormat:#"%#;%#:%i", username, IP, PORT]];
[packet writeData:dataOut];
}
Which calls:
- (void)writeData:(NSOutputStream *)dataOut
{
[super writeData:dataOut]; //Writes the "header" which is a char with the value of 0x02 (char packetID = 0x02)
NSUInteger len = [string lengthOfBytesUsingEncoding:NSUTF16BigEndianStringEncoding]; //Getting the length of the string i guess?
NSData *data = [string dataUsingEncoding:NSUTF16BigEndianStringEncoding]; //Getting string bytes?
[dataOut write:(uint8_t*)len maxLength:2]; //Send the length?
[dataOut write:[data bytes] maxLength:[data length]]; //Send the actual string?
}
I have established a successful connection to the server beforehand, but I don't really know whether or not I am sending the packets correctly. Could somebody please explain how I should send various data types and objects. (int, byte/char, short, double, NSString, BOOL/bool)
Also, is there any specific or universal way to send packets like the ones required by Minecraft?
Ok, I guess the question is now: how do data types, mainly strings, relate in Java and Objective-C?
Any help is appreciated, thank you!
Nobody knows?
Maybe you're running into a network/host byte order problem? I know very little about Minecraft- but I note that it's mentioned here that shorts in the Minecraft protocol use network byte order, which is big-endian (all other data types are 1 byte long so endianness is not relevant).
All x86 machines use little-endian.
I don't know whether your PacketHandshake class is converting the data before sending it- if not you could use the c library functions ntohs() and htons(), for which you'd need to include sys/types.h and
netinet/in.h
The link also mentions that strings are 64 byte array of standard ASCII chars, padded with 0x20s. You can get the ASCII value out of an NSString by doing [string UTF8String], which returns const char*- i.e. your standard C String ending with a 0x0, and then maybe pad it. But if it just works in Java, then maybe you don't need to.

Objective-C Packing Data using NSMutableData?

I need to put a short and integer at the begging of a message that i am sending to a java server. The server is expecting to read a short (message id) then an integer (message length). I've read in the stackoverflow that NSMutableData is similar to java ByteBuffer.
I am trying to pack the message into NSMutableData then send it.
So this is what I have but is not working !.
NSMutableData *data = [NSMutableData dataWithLength:(sizeof(short) + sizeof(int))];
short msg_id = 2;
int length = 198;
[data appendBytes:&msg_id length:sizeof(short)];
[data appendBytes:&length length:sizeof(int)];
send(sock, data, 6, 0);
The server is using Java ByteBuffer to read in the received data. So the bytes coming in is:
32,120,31,0,2,0
which is invalid.
The correct value so the ByteBuffer can read them as .getShort() and .getInt()
0,2,0,0,0,-66
You're basically putting stuff into the NSData object correctly, but you're not using it with the send function correctly. First off, as dreamlax suggests, use NSMutableData's -initWithCapacity initializer to get a capacity, not zeroed bytes.
Your data pointer is a pointer to an Objective-C (NSData) object, not a the actual raw byte buffer. The send function is a classic UNIX-y C function, and doesn't know anything about Objective-C objects. It expects a pointer to the actual bytes:
send(sock, [data bytes], [data length], 0);
Also, FWIW, note that endianness matters here if you're expecting to recover the multibyte fields on the server. Consider using HTONL and HTONS on the short and int values before putting them in the NSData buffer, assuming the server expects "network" byte order for its packet format (though maybe you control that).
I think your use of dataWithLength: will give you an NSMutableData object with 6 bytes all initialised to 0, but then you append 6 more bytes with actual values (so you'll end up with 12 bytes all up). I'm assuming here that short is 2 bytes and int is 4. I believe you want to use dataWithCapacity: to hint how much memory to reserve for your data that you are packing.
As quixoto has pointed out, you need to use the bytes method, which returns a pointer to the first byte of the actual data. The length method will return the number of bytes you have.
Another thing you need to watch out for is endianness. The position of the most significant byte is dependent on the underlying architecture.

how i can display a NSDATA description not in hex but in human redeable text?

I'm writing an iphone apps that receive data from an udp socket i can dispay what i receive using NSDATA description but is in hex format and for example it look like this:
<4c61742c 34343039 3131302e 35302c4c 6f6e2c39 38343237 352e3934 2c482c32 37392e30 302c4b6e 6f74732c 302e3032 2c4e616d 652c504c 41594552 2c496e64 65782c30 2c4d756c 7469706c 61796572 4e756d62 65722c30 00>
i know that thi is a prase of compite sens how i can convert it ?
NSString * s = [[[NSString alloc] initWithData:yourData encoding:NSUTF8StringEncoding] autorelease];
I'm going to assume you want to just debug the binary data. If that's not the case, what I describe below won't be terribly useful.
One technique I like is to use 0xED. Copy that big binary dump (everything inside the angle brackets) and paste it into a newly created 0xED document. You get a nice hex editor view.
0xED also supports user-defined plugins which can help visualize the binary data (for instance, converting an 8 byte timestamp to an NSDate)