Converting long to byte array - objective-c

I have java code:
Long long_value = 1;
ByteBuffer.allocate( 8).putLong( long_value).array();
I have result arrays of bytes: 0, 0, 0, 0, 0, 0, 0, 1 (in this order).
Please how correct port this code to Objective C?

Preamble
You say "in this order". When a multi-byte value is stored in memory the bytes can be stored big-endian - the most significant byte first, or little endian - the least significant byte first. For example the 2-byte hex value 0x1234 is stored as 0x12, 0x34 big-endian and 0x34, 0x12 little-endian. The endian order depends on the computer architecture in use, for example the Intel x86 is little-endian.
ByteBuffer is a Java class which stores values as byte according to its own endian flag, independent of the underlying hardware's endian order. The default setting of ByteBuffer is big-endian. In your sample you do not set this flag and the array you show is in big endian order.
Apple provides the functions described in Byte Order Utilities Reference for manipulating endian order. The function you need is CFSwapInt64HostToBig which takes a 64-bit signed or unsigned int in whatever endian order the host uses and returns an integer with the bytes arranged in big-endian order - the numeric value of the result is effectively meaningless at this point, it is an ordered collection of 8 bytes.
You also say you want 8 bytes, but a long may not be 8 bytes long - that depends on the hardware architecture, language and compiler. For example for OS X they are 8 bytes when compiling for 64-bit. There are two ways to address this, you can use the sizeof standard function which returns the number of bytes in a value or a type, you pass it a variable or a type name; or you can use the pre-defined sized types when you need a particular number of bytes, for example SInt64 is the pre-defined 8-byte signed integer type.
Finally you say you want an "array", but what kind of array? Objective-C/Cocoa has two: C language value arrays, and Objective-C object arrays NSArray and its mutable sibling NSMutableArray.
C language arrays: in C the name of an array variable is of type "pointer to element type", e.g. for the declaration float values[8] the type of values is float *. This means that pointers can be used as arrays, but they are not the same thing - a pointer variable holds a pointer to memory but does not allocate memory to point to, an array declaration allocates memory for its elements.
C Array
How to get a C "array" of bytes in big-endian order:
SInt64 long_value = 0x123456789ABCDEF; // use SInt64 rather than long
UInt64 BE_value = CFSwapInt64HostToBig(long_value); // use UInt64 as this value may not make numeric sense any more
UInt8 *BE_ptr = (UInt8 *)&BE_value; // UInt8 is a byte, take the address of BE_value
// BE_ptr is now a pointer to the 8 bytes of memory occupied by BE_value
// it can be treated as an array
// print it out to demo
for (int ix = 0; ix < 8; ix++)
{
NSLog(#"%d: %2x", ix, BE_ptr[ix]);
}
This will print out 12, 34 etc.
Objective-C array
You can build this on the above. You cannot store a byte directly in an Objective-C object, you must wrap it up as an object using NSNumber, and #() is a shorthand to do that:
SInt64 long_value = CFSwapInt64HostToBig(0x123456789ABCDEF);
UInt8 *BE_ptr = (UInt8 *)& long_value;
NSMutableArray *BE_array = [NSMutableArray arrayWithCapacity:8]; // create an object array
for (int ix = 0; ix < sizeof(long); ix++)
{
[BE_array addObject:#(BE_ptr[ix])]; // #(...) creates an NSNumber
}
NSLog(#"array: %#", BE_array);
This will print out the array (in decimal).
HTH

You could use a char pointer (chars are the same size as a byte, usually).
unsigned char *p = (unsigned char *)&myLong;
char byte1 = p[0];
char byte2 = p[1];
//etc...

Related

When to use size_t vs uint32_t?

When to use size_t vs uint32_t? I saw a a method in a project that receives a parameter called length (of type uint32_t) to denote the length of byte data to deal with and the method is for calculating CRC of the byte data received. The type of the parameter was later refactored to size_t. Is there a technical superiority to using size_t in this case?
e.g.
- (uint16_t)calculateCRC16FromBytes:(unsigned char *)bytes length:(uint32_t)length;
- (uint16_t)calculateCRC16FromBytes:(unsigned char *)bytes length:(size_t)length;
According to the C specification
size_t ... is the unsigned integer type of the result of the sizeof
operator
So any variable that holds the result of a sizeof operation should be declared as size_t. Since the length parameter in the sample prototype could be the result of a sizeof operation, it is appropriate to declare it as a size_t.
e.g.
unsigned char array[2000] = { 1, 2, 3 /* ... */ };
uint16_t result = [self calculateCRC16FromBytes:array length:sizeof(array)];
You could argue that the refactoring of the length parameter was pointlessly pedantic, since you'll see no difference unless:
a) size_t is more than 32-bits
b) the sizeof the array is more than 4GB

Is this conversion valid?

I've the code in Java where p1 is an object of Pixel class which accesses an array pixels and assigns it the value (at right side) at the proper index. R G and B are some int values.
p1.pixels[index] = 0xff000000 | (R << 16) | (G << 8 ) | B;
I'm converting this code in Objective C as follows.But I don't know whether I have to mention the object name (insert object at p1.pixels) or inserting object at pixels does the same?
int newNumber = 0xff000000 | (R << 16) | (G << 8 ) | B;
NSNumber *yourNumber = [NSNumber numberWithInt:newNumber];
[pixels insertObject:yourNumber atIndex:index];
NSArrays don't have a hard size limit like Java arrays do. They fill from the front, don't have default values (null in Java), and don't allow you to insert to an arbitrary location. The only way that the
[pixels insertObject:yourNumber atIndex:index];
line is safe is if there are greater than or equal to yourNumber elements already in the array.
If you really need that object to exist at a certain index, you should either fill the earlier positions with the other pixel values or a placeholder object like [NSNull null]
Also, int has different sizes on different Macs and iOS devices. If you want a specific sized integer, you should use one of the types like uint32, which is guaranteed to be 32-bits on every machine.
I think if you're manipulating pixels like this you're better off (in terms of performance and memory) to stick to plain-old-C.
If you wanted to create an UIImage object from the pixel data then you would use a buffer allocated using malloc(); for example (code taken from here - see the question for the rest of the code):
char* rgba = (char*)malloc(width*height*4);
for(int i=0; i < width*height; ++i) {
rgba[4*i] = buffer[3*i];
rgba[4*i+1] = buffer[3*i+1];
rgba[4*i+2] = buffer[3*i+2];
rgba[4*i+3] = 255;
}
Note that this is a byte buffer, not a uint32_t buffer, so adjust accordingly.
Using an NSArray populated with NSNumber objects will be much slower and take up much more space.

Sizeof C array with integers (in Obj-C)

myclass.h:
#define BUTTON_NAVI 41;
#define BUTTON_SETTINGS 42;
#define BUTTON_INFO 43;
myclass.m:
int btnNavi = BUTTON_NAVI;
int btnSettings = BUTTON_SETTINGS;
int btnArray[2] = {btnNavi, btnSettings};
NSLog(#"count = %i", sizeof(btnArray));
[self addToolbarButtons:btnArray];
-> Log: count = 8
8?! What did I do wrong?
And inside "addToolbarButtons" count is 4... :-(
EDIT:
- (void)addToolbarButtons:(int[])buttonIdArray {
NSLog(#"count = %i", sizeof(buttonIdArray));
}
-> Log: count = 4
sizeof is giving you the size in bytes, 8 bytes sounds right for 2 integers (32-bit or 4 bytes each).
If what you want is the length of the array, you can do sizeof(arr) / sizeof(arr[0]) which will give you the size of the entire array divided by the size of each element. In this case you will get 8 / 4 == 2, which is what I take it you expect.
EDIT
To answer your second question, when you pass the array to the method, you're actually passing a pointer to the array. Hence, the size of the pointer is also 32-bits or 4 bytes. If you want the function to know the length of the array, you need to also pass its length along with said pointer.
sizeof is giving the size of the array in bytes. An int is 4 bytes, so a 2-element array of ints will be 8 bytes.
However, sizeof won't do what you want in your method. When a C array is passed into a function (or method), it actually get passed as a pointer, and sizeof will return the size of a pointer. You should modify your method to take a length parameter:
- (void)addToolbarButtons:(int *)buttonIdArray length:(size_t)len
{
NSLog(#"count = %d", len);
}
The sizeof operator gives you the size in bytes of the thing you pass to it. If an int is 4 bytes, then an array of two ints is 8 bytes.
However, sizeof is a compile-time check on the variable itself. At runtime, the bounds of an array are not known — nor are they known outside the scope where the variable was defined. When you declare the argument (int[])buttonIdArray, the compiler desugars that to (int *)buttonArray — it's just a plain int pointer. So when you do sizeof(buttonArray), it tells you the size of a pointer, 4.
Because the language doesn't keep track of their size for you, using C arrays is a pain. You have to pass the number of elements in the array to every function and method that acts on it.

Problem while converting NSData to int

Using foundation and cocoa frameworks on Mac, I am trying to convert an NSData object in humanly understandable number.
Let say the NSData object is an image of NPIXEL. I know the binary data are coded in big endian and represent 32 bit integer (to be more precise 32 bit two complements integer). I write the piece of code bellow to convert the NSData into an int array. But the value I got are completely wrong (this does not means the measurement are bad, I used a special software to read the data and the value given by the software are different from the one I got with my code).
-(int *) GetArrayOfLongInt
{
//Get the total number of element into the Array
int Nelements=[self NPIXEL];
//CREATE THE ARRAY
int array[Nelements];
//FILL THE ARRAY
int32_t intValue;
int32_t swappedValue;
double Value;
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); Nbit/=sizeof(int32_t);
int i=0;
int step=sizeof(int32_t);
for(int bit=0; bit < Nbit; bit+=step)
{
[Img getBytes:&swappedValue range:NSMakeRange(bit,step)];
intValue= NSSwapBigIntToHost(swappedValue);
array[i]=intValue;
i++;
}
return array;
}
This piece of code (with minor change) work perfectly when the binary data represent float or double, but I dont when it is 16,32 or 64 bit integer. I also tried changingNSSapBigIntToHostintoNSSwapLittleInttoHost`. I even tried with long, but the results is still the same, I got bad values. What wrong I am doing ?
PS: Some of the variable in my code are already set elsewhere in my program. BITPIX is the bit size of each pixel. In this case 32. GCOUNT is equal to 1, PCOUNT 0 and Nelements is the total number of pixel I should have in my image.
Returning a pointer to a local variable is a very bad idea. array could get overwritten at any time (or if you were to write through the pointer, you could corrupt the stack). You probably want something like:
// CREATE THE ARRAY
int *array = malloc(Nelements * sizeof(int));
Your algorithm seems a bit overkill, too. Why not just copy out the whole array from the NSData object, and then byteswap the entries in place? Something like:
int32_t length = [Img length];
int32_t *array = malloc(length);
[Img getBytes:array length:length];
for (i = 0; i < length/sizeof(int32_t); i++)
{
array[i] = NSSwapBigIntToHost(array[i]);
}

How to declare 2D byte array

I am trying to make a 2D byte array.
Can anybody give the code how to declare a NULL 2D byte array in Objective-C?
Since objective-c is a strict superset of c, you could just use a pure c definition and it would work fine:
char** myMatrix = malloc(width*height);
You could also use an NSArray of NSArrays, but that's not a 2 dimensional array. It's a jagged array and considerably less easy to use than a plain byte array.
Another alternative is using an NSData/NSMutableData object. That is the Foundation way of working with byte arrays. See NSMutableData class reference for more information.
NSMutableData* data = [NSMutableData dataWithLength:1024]; // One kilobyte
void* dataPointer = [data mutableBytes]; // Get a pointer to the raw bytes
I'm cheating by doing this in C.
size_t width;
size_t height;
unsigned char *twoDimArray = calloc(width*height);