I need to store a series of 1s and 0s of arbitrary length.
I had planned to use ints, but then it occurred to me that really all I need is a bitstream.
NSMutableData seems like just the thing. Except all I see anyone talking about is how to set bytes on it, or store jpegs or strings in it. I need to get way more granular than that.
Given a series of 1s and 0s such as: 110010101011110110, how do I make it into an NSData object--and how do I get it out?
NSData's appendBytes:length: and mutableBytes are all at the byte level, and I need to start lower. Storing those 1s and 0s as bytes doesn't make sense, when the bytes themselves are made of sets of 1s and 0s. I'm having trouble finding anything telling me how to set bits.
Here's some faux code:
NSString *sequence = #"01001010000010"; //(or int sequence, or whatever)
for (...){//iterate through whatever it is--this isn't what I need help with
if ([sequence intOrCharOrWhateverAtIndex: index] == 0) {
//do something to set a bit -- this is what I need help with
} else {
//set the bit the other way -- again, this is what I need help with
}
}
NSData *data = [NSData something]; //wrap it up and save it -- help here too
Do you literally have 1s and 0s? Like... ASCII numerals? I would use NSString to store that. If by 1s and 0s you mean a bunch of bits, then just divide the number of bits by 8 to get the number of bytes and make an NSData of the bytes.
(Editing to add untested code to convert a bitstream to a buffer)
//Assuming the presence of an array of 1s and 0s stored as some numeric type, called bits, and the number of bits in the array stored in a variable called bitsLength
NSMutableData *buffer = [NSMutableData data];
for (int i = 0; i < bitsLength; i += 8) {
char byte = 0;
for (int bit = 0; bit < 8 && i + bit < bitsLength; bit++) {
if (bits[i + bit] > 0) {
byte += (1 << bit);
}
}
[buffer appendBytes:&byte length:1];
}
I got this answer from: Convert Binary to Decimal in Objective C
Basically, I think the question could be phrased, "how do I parse a string representation of a binary number into a primitive number type". The magic is all in strtol.
NSString* b = #"01001010000010";
long v = strtol([b UTF8String], NULL, 2);
long data[1];
data[0] = v;
NSData* d = [NSData dataWithBytes:data length:sizeof(data)];
[d writeToFile:#"test.txt" atomically:YES];
Using this idea, you could split your string into 64 character chunks and convert them to longs.
Related
I'm new in objective-C and I'm not getting to converting an audio file to char exactly I need. It is ignoring a sequence of zeros (0) and it's deforming the data structure.
My code is so:
-(NSString *) dataToHex:(NSData*) data {
const unsigned char *dbytes = (unsigned char*)[data bytes];
NSMutableString *hexStr =
[NSMutableString stringWithCapacity:[data length]/**2*/];
int i;
for (i = 0; i < [data length]; i++) {
[hexStr appendFormat:#"%x", dbytes[i]];
}
return [NSString stringWithString: hexStr];
}
Thank you very much.
If I understand your problem correctly the issue is with your format %x - this produces a hexadecimal text representation with sufficient digits to represent the value and without any leading zeroes.
For example the value 32 will produce the text 20, while the value 12 produces c - only one character long.
If you wish to convert to hex representation and then back again each of your byte values needs to produce the same number of characters - as otherwise you can't know where the boundaries are between each byte's representation.
To do this you can use the format %02x, which means always produce two characters padding with zeroes as required. For example with this format 12 will produce 0c.
HTH
I have an NSData packet with data in it. I need to convert the byte at range 8, 1 to an int. To get the data at that location I do the following.
NSData *byte = [packet subdataWithRange:NSMakeRange(8, 1)];
If I NSLog byte
<01>
How do I think convert this to an int? This is probably the most basic of questions but I am just not getting it right.
Any help would be appreciated.
Update
With that data the int should be equal to 1. I am not sure if this has anything todo with Endian.
use -[NSData bytes] to get raw buffer and read from it
int i = *((char *)[byte bytes])
or use -[NSData getBytes:length:]
char buff;
[bytes getBytes:&buff length:1];
int i = buff;
make sure you are reading from char * not int *, otherwise you are accessing invalid memory location, which may or may not crash or provide correct result.
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 get the value of a certain bit from a byte or integer? The only similar answer that I've been able to find is for a specific character inside a string. I am trying to convert a binary number to a decimal number, and perhaps there is a much simpler way to do this, but I was thinking of this: multiplying 2^(position of integer from right) by either a 1 or 0, depending on the value of the integer at the position previously mentioned. Any tips?
NSString * binary = #"0011010";
long value = strtol([b UTF8String], NULL, 2);
There are multiways of obtaining the value of bit within a byte or integer. It all depends on your needs.
One way would be to use a mask with bitwise operators.
int result = sourceValue & 8; // 8 -> 0x00001000
// result non zero if the 4th bit from the right is ON.
You can also shift bits one by one and read, say, the right-most bit.
for (int i = 0; i < 8; i++)
NSLog(#"Bit %d is %#", i, (sourceValue % 2 == 0) ? #"OFF" : #"ON");
sourceValue = sourceValue >> 1; // shift bits to the right for next loop.
}
Or if you just want the text representation for an integer, you could let NSNumber do the work:
NSString* myString = [[NSNumber numberWithInt:sourceValue] stringValue];
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]);
}