I have an Uint8List data list, for example:
Uint8List uintList = Uint8List.fromList([10, 1]);
How can I convert these numbers to a decimal number?
int decimalValue = ??? // in this case 265
Mees' answer is the correct general method, and it's good to understand how to do bitwise operations manually.
However, Dart does have a ByteData class that has various functions to help parse byte data for you (e.g. getInt16, getUint16). In your case, you can do:
Uint8List uintList = Uint8List.fromList([10, 1]);
int decimalValue = ByteData.view(uintList.buffer).getInt16(0, Endian.little);
print(decimalValue); // Prints: 266.
From what I understand of your question, you want decimalValue to be an integer where the least significant byte is (decimal)10, and the byte after that to be 1. This would result in the value 1 * 256 + 10 = 266. If you meant the bytes the other way around, it would be 10 * 256 + 1 = 2560 + 1 = 2561.
I don't actually have any experience with dart, but I assume code similar to this would work:
int decimalValue = 0;
for (int i = 0; i < uintList.length; i++) {
decimalValue = decimalValue << 8; // shift everything one byte to the left
decimalValue = decimalValue | uintList[i]; // bitwise or operation
}
If it doesn't produce the number you want it to, you might have to iterate through the loop backwards instead, which requires changing one line of code:
for (int i = uintList.length-1; i >= 0; i--) {
Related
I'm using bit shift operators on ints to convert to binary representation like that:
String toBinary(int i) {
var bytes = Uint8List(8);
bytes[0] = i >> 56;
bytes[1] = i >> 48;
bytes[2] = i >> 40;
bytes[3] = i >> 32;
bytes[4] = i >> 24;
bytes[5] = i >> 16;
bytes[6] = i >> 8;
bytes[7] = i;
return String.fromCharCodes(bytes);
}
Now I need to do the same thing for doubles, but double does not define bit shift operators. However, as doubles are also represented in 64 bit, is there a way to convert them to binary format?
First of all Dart already provides a ByteData class so in this case you can avoid using the bit shift operation and do instead:
var byteData = ByteData(8);
byteData.setUint64(0, 256);
var bytes = byteData.buffer.asUint8List();
which will produce the same byte list.
Given that you can use the setFloat64 method on ByteData to set a double and then get the binary representation.
The compiler produce a "warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll" and I don't understand why.
Here is the source code. It is a revisited itoa() function for HLSL producing resulting ascii codes in an array of uint.
#define ITOA_BUFFER_SIZE 16
// Convert uint to ascii and return number of characters
uint UIntToAscii(
in uint Num, // Number to convert
out uint Buf[ITOA_BUFFER_SIZE], // Where to put resulting ascii codes
in uint Base) // Numeration base for convertion
{
uint I, J, K;
I = 0;
while (I < (ITOA_BUFFER_SIZE - 1)) { // <==== Warning X3557
uint Digit = Num % Base;
if (Digit < 10)
Buf[I++] = '0' + Digit;
else
Buf[I++] = 'A' + Digit - 10;
if ((Num /= Base) == 0)
break;
}
// Reverse buffer
for (K = 0, J = I - 1; K < J; K++, J--) { // <==== Warning X3557
uint T = Buf[K];
Buf[K] = Buf[J];
Buf[J] = T;
}
// Fill remaining of buffer with zeros to make compiler happy
K = I;
while (K < ITOA_BUFFER_SIZE)
Buf[K++] = 0;
return I;
}
I tried to rewrite the while loop but this doesn't change anything. Also tried to use attribute [fastopt] without success. As far as I can see the function produce the correct result.
Any help appreciated.
The warning you are getting is
WAR_TOO_SIMPLE_LOOP 3557 The loop only executes for a limited number
of iterations or doesn't seem to do anything so consider removing it
or forcing it to unroll.
The warning is pretty much self explanatory, if you consider that loops are considered inefficient in GPGPU, so the compiler tries to unroll them when it's possible. What the compiler is telling you is that you created some loops that can run more efficiently if unrolled, or can be removed because they never run. If a loop is unrollable, it means that you can predict at compile time the number of times it will run. Your loops on first look should not fulfill this criterium.
I = 0;
while (I < (ITOA_BUFFER_SIZE - 1)) { // <==== Warning X3557
uint Digit = Num % Base;
if (Digit < 10)
Buf[I++] = '0' + Digit;
else
Buf[I++] = 'A' + Digit - 10;
if ((Num /= Base) == 0)
break;
}
This while loop runs up to 15 times I < (ITOA_BUFFER_SIZE - 1), depending on (Num /= Base) == 0. Final value of I is between 1 and 15, depending on how if ((Num /= Base) == 0) evaluates on each cycle. Nonetheless, it still is unrollable, because the compiler may still insert a conditional jump over the iterations.
// Reverse buffer
for (K = 0, J = I - 1; K < J; K++, J--) { // <==== Warning X3557
uint T = Buf[K];
Buf[K] = Buf[J];
Buf[J] = T;
}
This second loop, instead should not be unrollable, because I should not be known to the compiler.
The warning you reported
warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll
might refer to the first loop if if ((Num /= Base) == 0) always evaluates to true on first iteration. In that case, I would be equal to 1, and J would be equal to 0 on the second loop. That second loop would not run because K < J would evaluate to false on first iteration.
What you get in the end if you let it [unroll] is probably a single iteration on the while loop and the complete removal of the subsequent for loop. I highly suspect this is not your intended behaviour, and while it might suppress the warning, you might want to check the code and see if something does not run the way it should.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I am working on a app which sends data to server with user location info. Server accept this data based on checksum calculation, which is written in java.
Here is the code written in Java:
private static final String CHECKSUM_CONS = "1217278743473774374";
private static String createChecksum(double lat, double lon) {
int latLon = (int) ((lat + lon) * 1E6);
String checkSumStr = CHECKSUM_CONS + latLon;
byte buffer[] = checkSumStr.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
byte readBuffer[] = new byte[50];
long value = 0;
try {
while (cis.read(readBuffer) >= 0) {
value = cis.getChecksum().getValue();
}
} catch (Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
return String.valueOf(value);
}
I tried looking for help to find out how to write objective c equivalent of this. Above function uses adler32 and I don't have any clue about that. Please help.
Thanks for your time.
The answers shown here by #achievelimitless and #user3275097 are incorrect.
First off, signed integers should not be used. The modulo operator on negative numbers is defined differently in different languages, and should be avoided when possible. Simply use unsigned integers instead.
Second, the loops will quickly overflow the 16-bit accumulators, which will give the wrong answer. The modulo operations can be deferred, but they must be done before overflow. You can calculate how many loops you can do safely by assuming that all of the input bytes are 255.
Third, because of the second point, you should not use 16-bit types. You should use at least 32-bit types to avoid having to do the modulo operation very often. You still need to limit the number of loops, but the number gets much bigger. For 32-bit unsigned types, the maximum number of loops is 5552. So the basic code looks like:
#define MOD 65521
#define MAX 5552
unsigned long adler32(unsigned char *buf, size_t len)
{
unsigned long a = 1, b = 0;
size_t n;
while (len) {
n = len > MAX ? MAX : len;
len -= n;
do {
a += *buf++;
b += a;
} while (--n);
a %= MOD;
b %= MOD;
}
return a | (b << 16);
}
As noted by #Sulthan, you should simply use the adler32() function provided in zlib, which is already there on Mac OS X and iOS.
On basis of definition of adler32 checksum as mentioned in wikipedia,
Objective C implementation would be like this:
static NSNumber * adlerChecksumof(NSString *str)
{
NSMutableData *data= [[NSMutableData alloc]init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
for (int i = 0; i < ([str length] / 2); i++)
{
byte_chars[0] = [str characterAtIndex:i*2];
byte_chars[1] = [str characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
int16_t a=1;
int16_t b=0;
Byte * dataBytes= (Byte *)[data bytes];
for (int i=0; i<[data length]; i++)
{
a+= dataBytes[i];
b+=a;
}
a%= 65521;
b%= 65521;
int32_t adlerChecksum= b*65536+a;
return #(adlerChecksum);
}
Here str would be your string as mentioned in your question..
So when you want to calculate checksum of some string just do this:
NSNumber * calculatedChkSm= adlerChecksumof(#"1217278743473774374");
Please Let me know if more info needed
How to get a 32 bit number in objective c when an byte array is passed to it, similarly as in java where,
ByteBuffer bb = ByteBuffer.wrap(truncation);
return bb.getInt();
Where truncation is the byte array.
It returns 32 bit number.. Is this possible in objective c?
If the number is encoded in little-endian within the buffer, then use:
int32_t getInt32LE(const uint8_t *buffer)
{
int32_t value = 0;
unsigned length = 4;
while (length > 0)
{
value <<= 8;
value |= buffer[--length];
}
return value;
}
If the number is encoded in big-endian within the buffer, then use:
int32_t getInt32BE(const uint8_t *buffer)
{
int32_t value = 0;
for (unsigned i = 0; i < 4; i++)
{
value <<= 8;
value |= *buffer++;
}
return value;
}
UPDATE If you are using data created on the same host then endianness is not an issue, in which case you can use a union as a bridge between the buffer and integers, which avoids some unpleasant casting:
union
{
uint8_t b[sizeof(int32_t)];
int32_t i;
} u;
memcpy(u.b, buffer, sizeof(u.b));
// value is u.i
Depending on the endianness:
uint32_t n = b0 << 24 | b1 << 16 | b2 << 8 | b3;
or
uint32_t n = b3 << 24 | b2 << 16 | b1 << 8 | b0
Not sure if you just want to read 4 bytes and assign that value to an integer. This case:
int32_t number;
memcpy(&number, truncation, sizeof(uint32_t));
About endianess
From your question (for me) was clear that the bytes were already ordered correctly. However if you have to re-order these bytes, use ntohl() after memcpy() :
number=ntohl(number);
I'm working on an app of hardware communication that I send or require data from an external hardware. I have the require data part done.
And I just find out I could use some help to calculate the checksum.
A package is created as NSMutableData, then it will be converted in to Byte Array before sending out.
A package looks like this:
0x1E 0x2D 0x2F DATA checksum
I'm thinking I can convert hex into binary to calculate them one by one. But I don't know if it's a good idea. Please let me know if this is the only way to do it, or there are some built in functions I don't know.
Any suggestions will be appreciated.
BTW, I just found the code for C# from other's post, I'll try to make it work in my app. If I can, I'll share it with you. Still any suggestions will be appreciated.
package org.example.checksum;
public class InternetChecksum {
/**
* Calculate the Internet Checksum of a buffer (RFC 1071 - http://www.faqs.org/rfcs/rfc1071.html)
* Algorithm is
* 1) apply a 16-bit 1's complement sum over all octets (adjacent 8-bit pairs [A,B], final odd length is [A,0])
* 2) apply 1's complement to this final sum
*
* Notes:
* 1's complement is bitwise NOT of positive value.
* Ensure that any carry bits are added back to avoid off-by-one errors
*
*
* #param buf The message
* #return The checksum
*/
public long calculateChecksum(byte[] buf) {
int length = buf.length;
int i = 0;
long sum = 0;
long data;
// Handle all pairs
while (length > 1) {
// Corrected to include #Andy's edits and various comments on Stack Overflow
data = (((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0xFF));
sum += data;
// 1's complement carry bit correction in 16-bits (detecting sign extension)
if ((sum & 0xFFFF0000) > 0) {
sum = sum & 0xFFFF;
sum += 1;
}
i += 2;
length -= 2;
}
// Handle remaining byte in odd length buffers
if (length > 0) {
// Corrected to include #Andy's edits and various comments on Stack Overflow
sum += (buf[i] << 8 & 0xFF00);
// 1's complement carry bit correction in 16-bits (detecting sign extension)
if ((sum & 0xFFFF0000) > 0) {
sum = sum & 0xFFFF;
sum += 1;
}
}
// Final 1's complement value correction to 16-bits
sum = ~sum;
sum = sum & 0xFFFF;
return sum;
}
}
When I post this question a year ago, I was still quite new to Objective-C. It turned out to be something very easy to do.
The way you calculate checksum is based on how checksum is defined in your communication protocol. In my case, checksum is just the sum of all the previous bytes sent or the data you want to send.
So if I have a NSMutableData *cmd that has five bytes:
0x10 0x14 0xE1 0xA4 0x32
checksum is the last byte of 0x10+0x14+0xE1+0xA4+0x32
So the sum is 01DB, checksum is 0xDB.
Code:
//i is the length of cmd
- (Byte)CalcCheckSum:(Byte)i data:(NSMutableData *)cmd
{ Byte * cmdByte = (Byte *)malloc(i);
memcpy(cmdByte, [cmd bytes], i);
Byte local_cs = 0;
int j = 0;
while (i>0) {
local_cs += cmdByte[j];
i--;
j++;
};
local_cs = local_cs&0xff;
return local_cs;
}
To use it:
Byte checkSum = [self CalcCheckSum:[command length] data:command];
Hope it helps.