I need exactly 1 byte for some kind of socket based application and i cant find a way to create it.
unsigned char mydata = 3;
[NSMutableData dataWithBytes:&mydata length:sizeof(mydata)];
NSData reference, unsigned char is used to save 1 byte.
Related
I have 4 distinct int values that I need to send to a BLE device (connection established OK).
I'll call the int values A,B,C,D for clarity. A and B range between 0-100, C has a range of 0-2000 and D has a range of 0-10000. All values are determined by user input.
I need to send these four values to the BLE device in quick succession, and package each of them differently: A and B (8 bits), C (16 bits) and D (32 bits). I'm unsure as to how to package the values correctly.
Below are three methods I've tried with varying degrees of success.
Convert int to data and send, e.g. for A (8 bit) int:
const unsigned char CHR = (float)A;
float size = sizeof(CHR);
NSData * aData = [NSData dataWithBytes:&CHR length:size];
[p writeValue:aData forCharacteristic:aCHAR type:CBCharacteristicWriteWithResponse];
Convert to string first, e.g. for (16 bit) C:
NSString * cString = [NSString stringWithFormat:#"%i",C];
NSData * cData = [cString dataUsingEncoding:NSUTF16StringEncoding];
[p writeValue:cData forCharacteristic:cCHAR type:CBCharacteristicWriteWithResponse];
Use uint, e.g. for (32 bit) D int:
uint32_t val = D;
float size = sizeof(val);
NSData * dData = [NSData dataWithBytes:(void*)&val length:size];
[p writeValue:valData forCharacteristic:dCHAR type:CBCharacteristicWriteWithResponse];
What am I doing wrong in the above, and how best to convert and send an int value to the device, allowing for the 3 formats required?
You need to know a little more information about the format your device expects:
Are the values signed or unsigned
Is the system little-endian or big-endian
Assuming that you want to use the little-endian format that iOS uses, you can just use dataWithBytes -
unsigned char a = 100
NSData *aData = [NSData dataWithBytes:&a length:sizeof(i)];
UInt16 c = 1000
NSData *cData = [NSData dataWithBytes:&c length:sizeof(c)];
Unit32 d = 10000
NSData *dData = [NSData dataWithBytes:&d length:sizeof(d)];
And then just write the NSData using writeValue:forCharacteristic:type:
If the device wants big-endian data then you will need to manipulate the bytes into the proper order. For this reason it is often easier just to send numeric values as ASCII strings and convert them back to numeric values on the receiving end, but this will depend on whether you have control over the format the device is expecting.
i am creating data packet in byteArray i want to convert char ch= "Q" to 3 bytes please help how to solve this.
char b[] = {0, 0, 'Q'};
NSData *d = [NSData dataWithBytes:b length:3];
You may need to swap the Q to a different position, depending on the precise byte order which is expected.
I have
char tem;
Its value is shown as blow:
Printing description of tem:
(char) tem = '\xd1'
which should equals to 209 in decimal.
My question is how can I implement this conversion programmatically? That is I want to get a NSInteger that equals 209 in this case.
Maybe there’s something I’m overlooking here, but given that both char and NSInteger are integral types, can’t you just do
char tem = '\xd1';
NSInteger i = tem;
? Or perhaps, to avoid surprises from sign extension,
NSInteger i = tem & 0xff;
A char variable actually is a 8-bit integer. You don't have to convert it to a NSInteger to get its decimal value. Just explicitly tell the compiler to interpret it as an unsigned 8-bit integer, uint8_t:
char theChar = '\xd1';
NSLog(#"decimal: %d", (uint8_t)theChar); //prints 'decimal: 209'
To convert it to a NSInteger:
NSInteger decimal = (uint8_t)theChar;
If yours char in ANSCII, do this:
char a = '3';//example char
int i = (int)(a - '0');
I am using SecKeyEncrypt with a JSON formatted string as input. If pass SecKeyEncrypt a plainTextLength of less than 246, it works. If I pass it a length of 246 or more, it fails with return value: paramErr (-50).
It could be a matter of the string itself. An example of what I might send SecKeyEncrypt is:
{"handle":"music-list","sym_key":"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALeaEO7ZrjgOFGLBzBHZtQuzH2GNDYMLWP+fIFNu5Y+59C6HECY+jt0yOXXom2mzp/WYYI/9G+Ig8OD6YiKv2nMCAwEAAQ==","app_id":"xgfdt.LibraryTestApp","api_key":"7e080f74de3625b90dd293fc8be560a5cdfafc08"}
The 245th character is '0'.
The ONLY input that is changing between this working and is the plainTextLength. SecKeyGetBlockSize() is returning 256 to me, so any input up to 256 characters long should work.
Here is my encrypt method:
+ (NSData*)encrypt:(NSString*)data usingPublicKeyWithTag:(NSString*)tag
{
OSStatus status = noErr;
size_t cipherBufferSize;
uint8_t *cipherBuffer;
// [cipherBufferSize]
size_t dataSize = 246;//[data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
const uint8_t* textData = [[data dataUsingEncoding:NSUTF8StringEncoding] bytes];
SecKeyRef publicKey = [Encryption copyPublicKeyForTag:tag];
NSAssert(publicKey, #"The public key being referenced by tag must have been stored in the keychain before attempting to encrypt data using it!");
// Allocate a buffer
cipherBufferSize = SecKeyGetBlockSize(publicKey);
// this value will not get modified, whereas cipherBufferSize may.
const size_t fullCipherBufferSize = cipherBufferSize;
cipherBuffer = malloc(cipherBufferSize);
NSMutableData* accumulatedEncryptedData = [NSMutableData dataWithCapacity:0];
// Error handling
for (int ii = 0; ii*fullCipherBufferSize < dataSize; ii++) {
const uint8_t* dataToEncrypt = (textData+(ii*fullCipherBufferSize));
const size_t subsize = (((ii+1)*fullCipherBufferSize) > dataSize) ? fullCipherBufferSize-(((ii+1)*fullCipherBufferSize) - dataSize) : fullCipherBufferSize;
// Encrypt using the public key.
status = SecKeyEncrypt( publicKey,
kSecPaddingPKCS1,
dataToEncrypt,
subsize,
cipherBuffer,
&cipherBufferSize
);
[accumulatedEncryptedData appendBytes:cipherBuffer length:cipherBufferSize];
}
if (publicKey) CFRelease(publicKey);
free(cipherBuffer);
return accumulatedEncryptedData;
}
From the documentation:
plainTextLen
Length in bytes of the data in the plainText buffer. This must be less than or equal to the value returned by the SecKeyGetBlockSize function. When PKCS1 padding is performed, the maximum length of data that can be encrypted is 11 bytes less than the value returned by the SecKeyGetBlockSize function (secKeyGetBlockSize() - 11).
(emphasis mine)
You're using PKCS1 padding. So if the block size is 256, you can only encrypt up to 245 bytes at a time.
I am working on an OS project and I am just wondering how a pointer is stored in memory? I understand that a pointer is 4 bytes, so how is the pointer spread amongst the 4 bytes?
My issue is, I am trying to store a pointer to a 4 byte slot of memory. Lets say the pointer is 0x7FFFFFFF. What is stored at each of the 4 bytes?
The way that pointer is stored is same as any other multi-byte values. The 4 bytes are stored according to the endianness of the system. Let's say the address of the 4 bytes is below:
Big endian (most significant byte first):
Address Byte
0x1000 0x7F
0x1001 0xFF
0x1002 0xFF
0x1003 0xFF
Small endian (least significant byte first):
Address Byte
0x1000 0xFF
0x1001 0xFF
0x1002 0xFF
0x1003 0x7F
Btw, 4 byte address is 32-bit system. 64-bit system has 8 bytes addresses.
EDIT:
To reference each individual part of the pointer, you need to use pointer. :)
Say you have:
int i = 0;
int *pi = &i; // say pi == 0x7fffffff
int **ppi = π // from the above example, int ppi == 0x1000
Simple pointer arithmetic would get you the pointer to each byte.
You should read up on Endianness. Normally you wouldn't work with just one byte of a pointer at a time, though, so the order of the bytes isn't relevant.
Update: Here's an example of making a fake pointer with a known value and then printing out each of its bytes:
#include <stdio.h>
int main(int arc, char* argv[]) {
int *p = (int *) 0x12345678;
unsigned char *cp = (unsigned char *) &p;
int i;
for (i = 0; i < sizeof(p); i++)
printf("%d: %.2x\n", i, cp[i]);
return 0;
}