How to set a byte in NSMutableData - objective-c

How would I set a byte in an NSMutableData object?
I tried the following:
-(void)setFirstValue:(Byte)v{
[mValues mutableBytes][0] = v;
}
But that makes the compiler cry out loud...

But that makes the compiler cry out loud...
That is because mutableBytes* returns void*. Cast it to char* to fix the problem:
((char*)[mValues mutableBytes])[0] = v;
You could also use replaceBytesInRange:withBytes:
char buf[1];
buf[0] = v;
[mValues replaceBytesInRange:NSMakeRange(0, 1) withBytes:buf];

I cast it to an array
NSMutableData * rawData = [[NSMutableData alloc] initWithData:data];
NSMutableArray * networkBuffer = [[NSMutableArray alloc]init];
const uint8_t *bytes = [self.rawData bytes];
//cycle through data and place it in the network buffer
for (int i =0; i < [data length]; i++)
{
[networkBuffer addObject:[NSString stringWithFormat:#"%02X", bytes[i]]];
}
then of course you can just adjust objects in your networkBuffer (which is an nsmutablearray)

Related

How do I do a bit-wise XOR on NSData in Objective-C?

I have two NSData objects, data1 and data2, and I'd like to do a bit-wise XOR and store the result in a third NSData object, xorData.
The first thing I tried was this:
*data1.bytes^*data2.bytes;
but it gave an error of:
Invalid operands to binary expression ('const void' and 'const void')
So I tried to write a function that would extract the bytes of the data into an array of integers, perform the xor on the integers, then save the result back into an NSData object. The function looks like this:
+(NSData *) DataXOR1:(NSData *) data1
DataXOR2:(NSData *)data2{
const int *data1Bytes = [data1 bytes];
const int *data2Bytes = [data2 bytes];
NSMutableArray *xorBytes = [[NSMutableArray alloc] init ];
for (int i = 0; i < data1.length;i++){
[xorBytes addObject:[NSNumber numberWithInt:(data1Bytes[i]^data2Bytes[i])]];
}
NSData *xorData = [NSKeyedArchiver archivedDataWithRootObject:xorBytes];
return xorData;
}
This runs, but gives the wrong answers. When I test it on two simple pieces of data (data1 = 0x7038 and data2 = 0x0038), and use NSLog to output what the values are, I get:
data1Bytes[0] = 8070450532247943280
data2Bytes[0] = 8070450532247943168
data1Bytes[0]^data2Bytes[0] = 112
data1Bytes[1] = 10376302331560798334
data2Bytes[1] = 10376302331560798334
data1Bytes[1]^data2Bytes[1] = 0
This boggles my mind a bit because the values in the dataXBytes arrays are totally wrong, but they're xor-ing to the right values! (0x70 ^ 0x00 = 0x70 = 112)
I think it might be an endian-ness problem, but when I change the initialization of data1Bytes to:
const int *data1Bytes = CFSwapInt32BigToHost([data1 bytes]);
it runs into an error when it tries to access it, saying:
Thread 1: EXC_BAD_ACCESS(code=1, address = 0xa08ad539)
Is there a much simpler way to do the xor? If not, how can I fix the endian problem?
Casting to int then archiving an NSArray of NSNumbers will definitely not create the result you're looking for. You'll want to have some mutable NSData to which you append the individual bytes to, something like
+(NSData *) DataXOR1:(NSData *) data1
DataXOR2:(NSData *)data2{
const char *data1Bytes = [data1 bytes];
const char *data2Bytes = [data2 bytes];
// Mutable data that individual xor'd bytes will be added to
NSMutableData *xorData = [[NSMutableData alloc] init];
for (int i = 0; i < data1.length; i++){
const char xorByte = data1Bytes[i] ^ data2Bytes[i];
[xorData appendBytes:&xorByte length:1];
}
return xorData;
}
+ (NSData *) xorData:(NSData *)data1 with:(NSData *)data2
{
// make data1 smaller
if (data1.length > data2.length) {
NSData *t = data1;
data1 = data2;
data2 = t;
}
char *xor = (char *) malloc(data2.length * sizeof(char));
char * data1Bytes = (char *) data1.bytes;
char * data2Bytes = (char *) data2.bytes;
for (int i = 0; i <data1.length; i++)
{
xor[i] = data1Bytes[i] ^ data2Bytes[i];
}
NSMutableData *data = [[[NSMutableData alloc] initWithBytes:xor length:data1.length] autorelease];
[data appendData:[data2 subdataWithRange:NSMakeRange(data1.length, data2.length - data1.length)]];
free(xor);
return [NSData dataWithData:data];
}

XOR'ing two hex values stored as an NSString?

here is yet another silly question from me!
NSString *hex1 = #"50be4f3de4";
NSString *hex2 = #"30bf69a299";
/* some stuff like result = hex1^hex2; */
NSString *result = #"6001269f7d";
I have a hex value as a string, stored in two diff. variables. i need to Xor them and the result should be in another string variables?
i tried them by converting string --> NSData --> bytes array --> xor'ing them ...but i have no success.....
thank you in advance...
You have to convert every character to Base16(for hexadecimal) format first.Then you should proceed with XORing those characters.You can use the strtol() function to achieve this purpose.
NSString *hex1 = #"50be4f3de4";
NSString *hex2 = #"30bf69a299";
NSMutableArray *hexArray1 = [self splitStringIntoChars:hex1];
NSMutableArray *hexArray2 = [self splitStringIntoChars:hex2];
NSMutableString *str = [NSMutableString new];
for (int i=0; i<[hexArray1 count]; i++ )
{
/*Convert to base 16*/
int a=(unsigned char)strtol([[hexArray1 objectAtIndex:i] UTF8String], NULL, 16);
int b=(unsigned char)strtol([[hexArray2 objectAtIndex:i] UTF8String], NULL, 16);
char encrypted = a ^ b;
NSLog(#"%x",encrypted);
[str appendFormat:#"%x",encrypted];
}
NSLog(#"%#",str);
Utility method that i used to split characters of the string
-(NSMutableArray*)splitStringIntoChars:(NSString*)argStr{
NSMutableArray *characters = [[NSMutableArray alloc]
initWithCapacity:[argStr length]];
for (int i=0; i < [argStr length]; i++)
{
NSString *ichar = [NSString stringWithFormat:#"%c", [argStr characterAtIndex:i ]];
[characters addObject:ichar];
}
return characters;
}
Hope it helps!!

Obj-C How to convert NSData to an array of ints?

I have a NSData item that is holding a bunch of ints. How do I go about getting them out and into an NSArray?
The memory structure in the NSData is 32-bit int in little-endian order, one right after the other.
Sorry for the basic question, but still learning the obj-c way of doing things :)
You can use the functions defined in OSByteOrder.h to deal with endianness. Aside from that quirk, this is really just a matter of grabbing the byte buffer and iterating over it.
// returns an NSArray containing NSNumbers from an NSData
// the NSData contains a series of 32-bit little-endian ints
NSArray *arrayFromData(NSData *data) {
void *bytes = [data bytes];
NSMutableArray *ary = [NSMutableArray array];
for (NSUInteger i = 0; i < [data length]; i += sizeof(int32_t)) {
int32_t elem = OSReadLittleInt32(bytes, i);
[ary addObject:[NSNumber numberWithInt:elem]];
}
return ary;
}
Sounds like there are cleaner ways to do what you're trying to do, but this should work:
NSData *data = ...; // Initialized earlier
int *values = [data bytes], cnt = [data length]/sizeof(int);
for (int i = 0; i < cnt; ++i)
NSLog(#"%d\n", values[i]);
This answer is very similar to other answers above, but I found it instructive to play with casting the NSData bytes back to an int32_t[] array. This code works correctly on a little-endian processor (x64 in my case) but would be silently wrong on big-endian (PPC) because the byte representation would be big-endian.
int32_t raw_data[] = {0,1,2,3,4,5,6,7,8,9,10};
printf("raw_data has %d elements\n", sizeof(raw_data)/sizeof(*raw_data));
NSData *data = [NSData dataWithBytes:(void*)raw_data length:sizeof(raw_data)];
printf("data has %d bytes\n", [data length]);
int32_t *int_data_out = (int32_t*) [data bytes];
for (int i=0; i<[data length]/4; ++i)
printf("int %d = %d\n", i, int_data_out[i]);
[data release];
One possible solution below.
To take endianness into account, look up Core Endian Reference in the XCode doc set (you probably would use EndianS32_LtoN (32 bit litte endian to native endianness)).
int mem[]= {0x01, 0x02, 0x03, 0x04, 0xff};
NSData * data = [NSData dataWithBytes:mem length:sizeof(mem)*sizeof(int)];
NSMutableArray * ar = [NSMutableArray arrayWithCapacity:10];
/* read ints out of the data and add them to the array, one at a time */
int idx=0;
for(;idx<[data length]/sizeof(int);idx+=sizeof(int))
[ar addObject:[NSNumber numberWithInt:*(int *)([data bytes] + idx)]];
NSLog(#"Array:%#", ar);

how convert [NSData length] to a NSData

ex:
NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
if len = 10000,
i hope i can convert 1000 to a NSData look like
char hoperesult[] = {0x10, 0x27, 0x00, 0x00}
and hoperesult[] must always 4 Bytes
So you want the length in 4 little-endian bytes, correct? I think this will do it:
unsigned int len = [data length];
uint32_t little = (uint32_t)NSSwapHostIntToLittle(len);
NSData *byteData = [NSData dataWithBytes:&little length:4];
(Note that most network protocols use big-endian, but you showed little-endian so that's what this does.)
I'm not 100% sure what you mean here, but I think you are attempting to fill hoperesult with the values found in the file at 'filePath'.
struct _hoperesult {
char data[4];
} *hoperesult;
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
NSRange offset;
offset.location = 0;
offset.length = sizeof(_hoperesult);
NSData *hoperesultData;
while( (offset.location + offset.length) < len ) {
hoperesultData = [data subdataWithRange:offset];
// the equivalent of your char hoperesult[] content...
hoperesult = [hoperesultData bytes]
}
An instance of NSData can return a pointer to the actual bytes of data using the "bytes" method. It returns a (const void *). You could in theory simply cast [data bytes] to a char * and use the offset directly; or you can do like in the above code and return smaller chucks of NSData.
Hope that helps!

Objective-C Iterating through an NSString to get characters

I have this function:
void myFunc(NSString* data) {
NSMutableArray *instrs = [[NSMutableArray alloc] initWithCapacity:[data length]];
for (int i=0; i < [data length]; i++) {
unichar c = [data characterAtIndex:i];
[instrs addObject:c];
}
NSEnumerator *e = [instrs objectEnumerator];
id inst;
while (inst = [e nextObject]) {
NSLog("%i\n", inst);
}
}
I think it fails at [instrs addObject:c]. It's purpose is to iterate through the hexadecimal numbers of an NSString. What causes this code to fail?
A unichar is not an object; it's an integer type.
NSMutableArray can only hold objects.
If you really want to put it into an NSMutableArray, you could wrap the integer value in an NSNumber object: [instrs addObject:[NSNumber numberWithInt:c]];
But, what's the point of stuffing the values into an array in the first place? You know how to iterate through the string and get the characters, why put them into an array just to iterate through them again?
Also note that:
the "%i" NSLog format expects an integer; you can't pass it an object
for hexadecimal output, you want "%x", not "%i"
If the function is only meant to display the characters as hexadecimal values, you could use:
void myFunc(NSString* data)
{
NSUInteger len = [data length];
unichar *buffer = calloc(len, sizeof(unichar));
if (!buffer) return;
[data getCharacters:buffer range:NSMakeRange(0, len)];
for (NSUInteger i = 0; i < len; i++)
NSLog(#"%04x", (unsigned) buffer[i]);
free(buffer);
}
This is just a little bit more efficient than your approach (also, in your approach you never release the instrs array, so it will leak in a non-garbage-collected environment).
If the string contains hexadecimal numbers, then you will want to repeatedly use an NSScanner's scanHexInt: method until it returns NO.
void myFunc(NSString* data)
{
NSScanner *scanner = [[NSScanner alloc] initWithString:data];
unsigned number;
while ([scanner scanHexInt:&number])
NSLog(#"%u", number);
[scanner release];
}