Reputation: 1177
I've been given the following C++
function to do a left bit rotation of a string, I need to implement it in Objective C
(Obviously I've added the logging bit at the bottom):
void left_rotate ( uint16_t *in,
uint16_t *out,
int16_t len,
int16_t shift )
{
int16_t i, j;
j = (len / 2) - 1;
for (i = 0; i < (len / 2); i++) {
out[i] = (uint16_t) (in[i] << shift);
if (i < j) {
out[i] |= in[i + 1] >> ((int16_t) len - shift);
} else {
out[i] |= in[0] >> ((int16_t) len - shift);
}
}
NSLog(@"In: %hd", (short)in);
NSLog(@"Out: %hd", (short)out);
unsigned char * char1 = out;
NSLog(@"Char: %s", char1);
NSData * data1 = [[NSData alloc] initWithBytes:char1 length:sizeof(char1)];
NSLog(@"Data: %@", data1);
}
However I'm not entirely sure how it's supposed to work. I've tried to call it as follows:
NSString * originStringData = @"acf7183f7673200BBA7719775b20393c4487fa008e13542f4013eb9b2eb7490e";
NSString * RotateNumber = @"0003";
NSData *data = originStringData;
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);
for(int i=0; i<sizeof(byteData); i++)
{
u_int16_t data2 = byteData[i];
int16_t shift1 = (short)[RotateNumber intValue];
u_int16_t out1;
left_rotate(&data2, &out1, sizeof(byteData),shift1);
}
However it returns:
<60055600><b8077b00><c1001c00><f9011f00>
Where as the string I actually want is:
67b8c1fbb399005dd3b8cbbad901c9e2243fd004709aa17a009f5cd975ba4875
What I need to do is perform a left bit rotation on the origin string by the Rotate Number. I'm willing to give anything a go right now so any help would be appreciated, I'm a bit stuck!
Cheers!
Adam
Upvotes: 1
Views: 331
Reputation: 644
It seems left_rotate doesn't work as you desire. You can write you own rotate function like this(it works as what you want):
#import <Foundation/Foundation.h>
char char_to_hex(char ch)
{
char* table = "0123456789abcdef";
char* str = strchr(table, tolower(ch));
if(str == NULL)
return -1;
return str - table;
}
NSString* left_rotate(NSString* source, NSUInteger shift)
{
if(shift >= [source length] * 4)
{
shift %= ([source length] * 4);
}
NSInteger index = shift / 4;
NSString* tmp = [source substringFromIndex:index];
NSString* left = [source substringToIndex:index+1];
tmp = [tmp stringByAppendingString:left];
shift %= 4;
//get the internal pointer;
const char* data = [tmp cStringUsingEncoding:NSASCIIStringEncoding];
NSString* result = [[NSString alloc] init];
for(NSInteger i = 0; i < strlen(data) - 1; i++)
{
char ch1 = char_to_hex(data[i]);
char ch2 = char_to_hex(data[i+1]);
if(ch1 < 0 || ch2 < 0)
return nil;
char ch = ((ch1 << shift) | (ch2 >> (4 - shift))) & 0xF;
result = [result stringByAppendingFormat:@"%x", ch];
}
return result;
}
int main(int argc, const char * argv[]) {
NSString* source = @"acf7183f7673200BBA7719775b20393c4487fa008e13542f4013eb9b2eb7490e";
NSString* result = left_rotate(source, 3);
NSLog(@"result:%@", result);
return 0;
}
Upvotes: 1
Reputation: 17715
I believe you pass the wrong types to your function, you want to convert your NSString*
to an array of int16
before you pass it, what you're doing however, is simply copying the bytes representing the string.
Simply put, if you copy the byes representing "1"
, you won't get the equivalent of 1
, you have to add some conversion.
Something along these lines (no error handling, assuming a lot of things from your input, adapt!)
for (NSUInteger i = 0; i < originStringData.length; ++i {
unichar oneChar = [originStringData characterAtIndex:i];
if (isnumber(oneChar)) {
byteData[i] = oneChar - '0';
} else {
byteData[i] = oneChar - 'a' + 10;
}
}
On top of that you want to allocate some space for your out
too, you're passing a pointer to a single int16
, allocate another array of the same size and pass that.
Upvotes: 0