How to display hexadecimal bytes using NSLog - objective-c

How can I display the following bytes using NSLog?
const void *devTokenBytes = [devToken bytes];

Assuming that devToken is of type NSData * (from the bytes call), you can use the description method on NSData to get a string containing the hexadecimal representation of the data's bytes. See the NSData class reference.
NSLog(#"bytes in hex: %#", [devToken description]);

If you want a hex sequence:
NSMutableString *hex = [NSMutableString stringWithCapacity:[devToken length]];
for (int i=0; i < [devToken length]; i++) {
[hex appendFormat:#"%02x", [devToken bytes][i]];
}

Related

How to handle 32bit unicode characters in a NSString

I have a NSString containing a unicode character bigger than U+FFFF, like the MUSICAL SYMBOL G CLEF symbol '𝄞'. I can create the NSString and display it.
NSString *s = #"A\U0001d11eB"; // "A𝄞B"
NSLog(#"String = \"%#\"", s);
The log is correct and displays the 3 characters. This tells me the NSString is well done and there is no encoding problem.
String = "A𝄞B"
But when I try to loop through all characters using the method
- (unichar)characterAtIndex:(NSUInteger)index
everything goes wrong.
The type unichar is 16 bits so I expect to get the wrong character for the musical symbol. But the length of the string is also incorrect!
NSLog(#"Length = %d", [s length]);
for (int i=0; i<[s length]; i++)
{
NSLog(#" Character %d = %c", i, [s characterAtIndex:i]);
}
displays
Length = 4
Character 0 = A
Character 1 = 4
Character 2 = .
Character 3 = B
What methods should I use to correctly parse my NSString and get my 3 unicode characters?
Ideally the right method should return a type like wchar_t in place of unichar.
Thank you
NSString *s = #"A\U0001d11eB";
NSData *data = [s dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
const wchar_t *wcs = [data bytes];
for (int i = 0; i < [data length]/4; i++) {
NSLog(#"%#010x", wcs[i]);
}
Output:
0x00000041
0x0001d11e
0x00000042
(The code assumes that wchar_t has a size of 4 bytes and little-endian encoding.)
length and charAtIndex: do not give the expected result because \U0001d11e
is internally stored as UTF-16 "surrogate pair".
Another useful method for general Unicode strings is
[s enumerateSubstringsInRange:NSMakeRange(0, [s length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
NSLog(#"%#", substring);
}];
Output:
A
𝄞
B

Iterate through NSData bytes

How can I iterate through [NSData bytes] one by one and append them to an NSMutableString or print them using NSLog()?
Rather than appending bytes to a mutable string, create a string using the data:
// Be sure to use the right encoding:
NSString *result = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
If you really want to loop through the bytes:
NSMutableString *result = [NSMutableString string];
const char *bytes = [myData bytes];
for (int i = 0; i < [myData length]; i++)
{
[result appendFormat:#"%02hhx", (unsigned char)bytes[i]];
}
Update! Since iOS 7, there's a new, preferred way to iterate through all of the bytes in an NSData object.
Because an NSData can now be composed of multiple disjoint byte array chunks under the hood, calling [NSData bytes] can sometimes be memory-inefficient, because it needs to flatten all of the underlying chunks into a single byte array for the caller.
To avoid this behavior, it's better to enumerate bytes using the enumerateByteRangesUsingBlock: method of NSData, which will return ranges of the existing underlying chunks, which you can access directly without needing to generate any new array structures. Of course, you'll need to be careful not to go poking around inappropriately in the provided C-style array.
NSMutableString* resultAsHexBytes = [NSMutableString string];
[data enumerateByteRangesUsingBlock:^(const void *bytes,
NSRange byteRange,
BOOL *stop) {
//To print raw byte values as hex
for (NSUInteger i = 0; i < byteRange.length; ++i) {
[resultAsHexBytes appendFormat:#"%02x", ((uint8_t*)bytes)[i]];
}
}];

How to "concat" bytes from NSString and its length together?

I have a NSString [WORD] that has some length [LEN]. What i need to do is to get bytes from this string and put them together with length in short (2 bytes), so i would have [WORD] [LEN].
E.g.
String "AB" in utf8 HEX is 4142. Length of this string is 2==> 0002 in HEX.
So everything together is 41420002. How to get this bytes together?
I think this code does what you want.
NSString *myString = #"AB";
const char *chars = [myString UTF8String];
NSMutableString * result = [NSMutableString string];
for (int i=0; i < [myString length]; i++) {
[result appendFormat:#"%X", chars[i]];
}
[result appendFormat:#"%04X", [myString length]];
NSLog(#"%#", result);
Hope it helps!

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];
}