Want to create byte array in objective c - ios

i want to create a byte array in objective c, i am not able to find equivalent code of java's ByteArrayOutputStream and DataOutputStream.
for eg..
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeLong(counter); //counter is a long data type for eg 1165620611
dos.flush();
byte[] data = bos.toByteArray();
return data;
this code actually returns eight byte array...Here's the output in java
[0,0,0,0,69,121,-11,-125]
this is what i want exactly in objective c..

// #1 long to char array
long l = 1165620611;
char bytes[sizeof(long)];
memcpy(bytes,&l,sizeof(l));
// #2 char array to nsdata
int size = sizeof(bytes)/sizeof(char);
NSData *data = [NSData dataWithBytes:bytes length:size];
// #3 nsdata to char array
char buffer[size];
[data getBytes:buffer length:size];
// #4 prints char array: 0 0 0 0 69 121 -11 -125
while (0<size--) {
NSLog(#"%d",buffer[size]);
}
NSData is not needed at all, you can skip steps #2 and #3.

use char buff[] array in objective - c

You can use NSData & NSMutableData classes for this.
NSData and its mutable subclass NSMutableData provide data objects,
object-oriented wrappers for byte buffers. Data objects let simple
allocated buffers (that is, data with no embedded pointers) take on
the behavior of Foundation objects.
NSData creates static data objects, and NSMutableData creates dynamic
data objects. NSData and NSMutableData are typically used for data
storage and are also useful in Distributed Objects applications, where
data contained in data objects can be copied or moved between
applications.
The size of the data is subject to a theoretical limit of about 8
ExaBytes (in practice, the limit should not be a factor).
NSData is “toll-free bridged” with its Core Foundation counterpart,
CFDataRef. See “Toll-Free Bridging” for more information on toll-free
bridging.

Related

How to convert Objective-C NSData to Swift Data?

I have a NSData in Objective-C, the NSData has value 0x10, code like bellows:
#implementation BufUtil
+ (NSData *_Nonnull) getOCBuf {
std::vector<uint8_t> sendData = {0x10};
NSData * reqBuf = [[NSData alloc] initWithBytesNoCopy:sendData.data() length:sendData.size() freeWhenDone:false];
NSLog(#"getOCBuf, oc NSData reqBuf:%#", reqBuf);
return reqBuf;
}
#end
Then I use the data in Swift, Swift auto convert Objective-C NSData to Swift Data, but strange things happen, the value in Swift Data is 0x60, code like belows:
public func getOCBuf() -> Data {
let data = BufUtil.getOCBuf();
print("getOCBuf: swift data: \(data.hexEncodedString())")
return data
}
the log is like:
getOCBuf, oc NSData reqBuf:{length = 1, bytes = 0x10}
getOCBuf: swift data: 60
Now I am confused with what happened. Why 0x10 turn into 0x60, the two number not Binary complement.
Can anybody help me, thanks.
the code:
https://github.com/oncealong/SwiftOcDataConvert
It's my falut.
I copy code "how to convert from std::vector to NSData" from stackoverflow, but the code use [NSData alloc] initWithBytesNoCopy, which lead to all this.
the momory associate with the std::vector has freed after the getOCBuf func return. but the oc NSData and swift Data don't know. it use the origin address and found different value.
To be honest, the app should be crashed, and give a reason.

How to get the length of a struct in Obj-C?

int realLen = *((int*)((char*)sData.pData + 2));
NSLog(#"realLen = %d", realLen);
NSData* data = [NSData dataWithBytesNoCopy:sData.pData length:realLen freeWhenDone:NO];
sData is a struct type and pData is a void* type in its property;
How can it get the correct length?
So you want to store the address stored in sData.pData in an NSData object? That is odd, and probably not proper memory management.
If that is what you want to do, you can use this:
int realLen = sizeof(sData.pData)
However, if what you want to do is to copy the data that sData.pData points to into your NSDats, you're out of luck. A C style void* does not let you tell the size of the thing it's pointing to. You have to know the size of the data.

How to Convert NSValue to NSString

Some background... I am writing code that interacts with javascript via a ObjC-JS bridge utilizing UIWebView's stringByEvaluatingJavaScriptFromString:. The idea is that the "brains" of the app be in JS which tells Objective-C how to behave. There are multiple benefits to this like reduced binary size, flexible updates, etc. However, there is a case where there is some Objective-C only object that the JS needs to have a reference to (JS instructs ObjC when to use/remove the object). This is being done by placing the native object in a dictionary with a unique identifier which can be passed as a string to JS (over the bridge). My problem stems with coming up with a nice identifier for said native Objective-C object.
Thus, I am trying to convert a reference to an object to a string with no luck. This is what I have:
// anObject is a custom class
NSValue *handle = [NSValue valueWithPointer:(__bridge const void *)anObject];
NSData *data = [NSData dataWithValue:handle];
NSString *stringHandle = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
The dataWithValue: function (taken from this SO post):
+ (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;
}
Walking through it in the debugger shows me a nil value for stringHandle:
What am I doing wrong?
What you're doing wrong is trying to treat an address as if it's a UTF-8 encoded string. An address -- or any other chunk of arbitrary data -- isn't very likely to be valid UTF-8 data. (If by chance it were, it still wouldn't be the string you expect.)
If you're trying to get a string containing the pointer value, i.e., the address of the original object, that's just [NSString stringWithFormat:#"%p", anObject];
If you really need to do it from the NSValue, then replace anObject with [theValue pointerValue].
If you want to pretty-print arbitrary data, see How to convert an NSData into an NSString Hex string?
You can get a string representation by calling the NSObject method "description". You can override the "description" method in a subclass if you need.
An NSValue of a pointer will be an object holding the 4 bytes of the 32-bit pointer. It will not hold any of the data pointed to in RAM.

Why does the following code return incorrect values from NSData?

I need to send data across the network as NSData. As the format may be determined only at runtime, (e.g.: Message Type, number of objects etc, types of objects), I am using the following code to pack / unpack the NSData
To pack:
NSMutableData *data = [NSMutableData dataWithCapacity:0];
unsigned int _state = 66;
[data appendBytes:&state length:sizeof(state)];
To unpack (after receiving on a different iOS device)
void *buffer = malloc(255);
[data getBytes:buffer length:sizeof(unsigned int)];
unsigned int _state = (unsigned int)buffer;
....
I am using the buffer, because eventually there will be many different ints/ floats etc stored in the NSData. The first int may determine the type of message, second int - the number of floats stored, etc... I send and receive the data using apples game center apis:
- (BOOL)sendData:(NSData *)data toPlayers:(NSArray *)playerIDs withDataMode:(GKMatchSendDataMode)mode error:(NSError **)error
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
But the problem is, when I unpack the single int, instead of getting 66, I get some random value like 401488960 or 399903824 (its different each time I unpack, even though I am sending 66 each time). Why is the data incorrect? Am I unpacking incorrectly?
You are casting the pointer buffer to unsigned int: you are assigning the memory address to _state, not the value at that address. Use a pointer of the appropriate type (unsigned int *) instead, and dereference it:
unsigned int _state = *(unsigned int *)buffer;

Obfuscating a number(in a string) Objective C

I'm using the following code to obfuscate a passcode for a test app of mine.
- (NSString *)obfuscate:(NSString *)string withKey:(NSString *)key
{
// Create data object from the string
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
// Get pointer to data to obfuscate
char *dataPtr = (char *) [data bytes];
// Get pointer to key data
char *keyData = (char *) [[key dataUsingEncoding:NSUTF8StringEncoding] bytes];
// Points to each char in sequence in the key
char *keyPtr = keyData;
int keyIndex = 0;
// For each character in data, xor with current value in key
for (int x = 0; x < [data length]; x++)
{
// Replace current character in data with
// current character xor'd with current key value.
// Bump each pointer to the next character
*dataPtr = *dataPtr++ ^ *keyPtr++;
// If at end of key data, reset count and
// set key pointer back to start of key value
if (++keyIndex == [key length])
keyIndex = 0, keyPtr = keyData;
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
This works like a charm with all strings, but i've ran into a bit of a problem comparing the following results
NSLog([[self obfuscate:#"0000", #"maki"]); //Returns 0]<W
NSLog([[self obfuscate:#"0809", #"maki"]); //Returns 0]<W
As you can see, the two strings with numbers in, while different, return the same result! Whats gone wrong in the code i've attached to result in the same result for these two numbers?
Another example:
NSLog([self obfuscate:#"8000" withKey:#"maki"]); //Returns 8U4_
NSLog([self obfuscate:#"8290" withKey:#"maki"]); //Returns 8U4_ as well
I may be misunderstanding the concept of obfuscation, but I was under the impression that each unique string returns a unique obfuscated string!
Please help me fix this bug/glitch
Source of Code: http://iosdevelopertips.com/cocoa/obfuscation-encryption-of-string-nsstring.html
The problem is your last line. You create the new string with the original, unmodified data object.
You need to create a new NSData object from the modified dataPtr bytes.
NSData *newData = [NSData dataWithBytes:dataPtr length:data.length];
return [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
But you have some bigger issues.
The calls to bytes returns a constant, read-only reference to the bytes in the NSData object. You should NOT be modifying that data.
The result of your XOR on the character data could, in theory, result in a byte stream that is no longer a valid UTF-8 encoded string.
The obfuscation algorithm that you have selected is based on XORing the data and the "key" values together. Generally, this is not very strong. Moreover, since XOR is symmetric, the results are very prone to producing duplicates.
Although your implementation is currently broken, fixing it would not be of much help in preventing the algorithm from producing identical results for different data: it is relatively straightforward to construct key/data pairs that produce the same obfuscated string - for example,
[self obfuscate:#"0123" withKey:#"vwxy"]
[self obfuscate:#"pqrs" withKey:#"6789"]
will produce identical results "FFJJ", even though both the strings and the keys look sufficiently different.
If you would like to "obfuscate" your strings in a cryptographically strong way, use a salted secure hash algorithm: it will produce very different results for even slightly different strings.

Resources