How to declare 2D byte array - objective-c

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);

Related

Converting long to byte array

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...

get float value from nsdata objective-c iOS

I am trying to get a float value from a NSData object which contains several hex values. e.g. EC 51 38 41
From this 4 Byte values i want to get the float value 11.52. How do i have to do this in xcode?
I have tried it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber, i created an Byte Array and tried float myFloat = *(float*)&myByteArray. All these Options i found here at stackoverflow.
I tested it in Windows with C# and there it was no problem:
byte[] bytes = new byte[4] { 0xEC, 0x51, 0x38, 0x41 };
float myFloat = System.BitConverter.ToSingle(bytes, 0);
Does anybody know how i have to do this in xcode???
Thanks, Benjamin
When converting binary data from a foreign protocol always make sure to include proper swapping for endianness:
uint32_t hostData = CFSwapInt32BigToHost(*(const uint32_t *)[data bytes]);
float value = *(float *)(&hostData);
You have to know the endianness of the encoded data. You might need to use CFSwapInt32LittleToHost instead.
NSData * data = ...; // loaded from bluetooth
float z;
[data getBytes:&z length:sizeof(float)];
Try this.
I have tries it with NSScanner (scanFloat, scanHexFloat), NSNumberformatter and NSNumber
You're barking up the wrong tree here. NSScanner is for scanning strings. NSNumber is not the same as NSData, and NSNumberFormatter won't work with NSData either.
NSData is a container for plain old binary data. You've apparently got a float stored in an NSData instance; if you want to access it, you'll need to get the data's bytes and then interpret those bytes however you like, e.g. by casting to float:
float *p = (float*)[myData bytes]; // -bytes returns a void* that points to the data
float f = *p;

Arbitrary precision bit manipulation (Objective C)

I need to do bit operations on representations of arbitrary precision numbers in Objective C. So far I have been using NSData objects to hold the numbers - is there a way to bit shift the content of those? If not, is there a different way to achieve this?
Using NSMutableData you can fetch the byte in a char, shift your bits and replace it with -replaceBytesInRange:withBytes:.
I don't see any other solution except for writing your own date holder class using a char * buffer to hold the raw data.
As you'll have spotted, Apple doesn't provide arbitrary precision support. Nothing is provided larger than the 1024-bit integers in vecLib.
I also don't think NSData provides shifts and rolls. So you're going to have to roll your own. E.g. a very naive version, which may have some small errors as I'm typing it directly here:
#interface NSData (Shifts)
- (NSData *)dataByShiftingLeft:(NSUInteger)bitCount
{
// we'll work byte by byte
int wholeBytes = bitCount >> 3;
int extraBits = bitCount&7;
NSMutableData *newData = [NSMutableData dataWithLength:self.length + wholeBytes + (extraBits ? 1 : 0)];
if(extraBits)
{
uint8_t *sourceBytes = [self bytes];
uint8_t *destinationBytes = [newData mutableBytes];
for(int index = 0; index < self.length-1; index++)
{
destinationBytes[index] =
(sourceBytes[index] >> (8-extraBits)) |
(sourceBytes[index+1] << extraBits);
}
destinationBytes[index] = roll >> (8-extraBits);
}
else
/* just copy all of self into the beginning of newData */
return newData;
}
#end
Of course, that assumes the number of bits you want to shift by is itself expressible as an NSUInteger, amongst other sins.

How do I convert a c-style char* array to NSArray?

a.H:
-(NSArray *) returnarray:(int) aa
{
unsigned char arry[1000]={"aa","vv","cc","cc","dd"......};
NSArray *tmpary=arry;
return tmpary;
}
a.c:
#include "a.H"
main (){
// how do I call returnarray function to get that array in main class
}
I need that array in main and I need to retain that array function in separate class.
Can someone please provide a code example to do this?
These lines:
unsigned char arry[1000]={"aa", "vv", "cc", "cc", "dd", ...};
NSArray *tmpary=arry;
Should instead be:
unsigned char arry[1000]={"aa", "vv", "cc", "cc", "dd", ...};
NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: 1000];
for (i = 0; i < 1000; i++)
{
[tmpary addObject: [NSString stringWithCString: arry[i] encoding:NSASCIIStringEncoding]];
}
This is because a C-style array (that is, int arr[10]; for example) are not the same as actual NSArray objects, which are declared as above.
In fact, one has no idea what an NSArray actually is, other than what the methods available to you are, as defined in the documentation. This is in contrast to the C-style array, which you are guaranteed is just a contiguous chunk of memory just for you, big enough to hold the number of elements you requested.
C-style arrays are not NSArray's so your assignment of arry (the definition of which has some typos, at least the unsighned part) is not valid. In addition, you call arry an array of char, but you assign it an array of null-terminated strings.
In general you need to loop and add all the elements of the C-style array to the NSArray.
I'm not sure why you must do it in main. If you want a global you can do it by declaring a global in another file. That said, you CANNOT assign a plain C data array to an objective C NSArray, which is different in nature entirely.

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