Reputation: 133
I have a tcp server written in c#. I have to write two client (c++ and javascript). I can deserialize decimal (16byte - 128bit) in c# client but I can't deserialize other languages.
Decimals not too big, I can use float or double.
When serialize decimal:
MemoryStream combinedMessage = new MemoryStream();
decimal d = 2135102.06m;
using (BinaryWriter writer = new BinaryWriter(combinedMessage, encoding))
{
writer.Write(d);
}
byte[] message = combinedMessage.ToArray();
Serialized as:
62 232 185 12 0 0 0 0 0 0 0 0 0 0 2 0
How I can deserialize decimal from byte[] in c++ and javascript?
Upvotes: 4
Views: 788
Reputation: 28789
The first 12 bytes are a little-endian 96-bit integer, byte 13 and 14 are unused (for now), byte 15 contains the scale (power of 10 to divide by), and byte 16 contains the sign bit in the MSB (other bits unused). The main difficulty lies in accurate conversion -- even if the decimal is "not too big", converting it to a float
or Number
can be done in ways that lose more or less accuracy.
The following routine isn't necessarily the most accurate way to convert decimals, nor the fastest, but if you are not overly concerned with either accuracy or speed it'll get the job done, and it has the benefit of being easy to translate to most any C-like language. Here it is in JavaScript:
var b = [ 62, 232, 185, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 ];
var d = 0.0;
for (var i = 11; i >= 0; --i) {
var k = b[i];
for (var j = 0; j != 8; ++j) {
d *= 2;
d += (k & 0x80) >> 7;
k <<= 1;
}
}
var scale = b[14];
d /= Math.pow(10, scale);
if (b[15] >= 0x80) d = -d;
This is almost valid C# already; all you need to change is Math.Pow
and byte[] b = { 62 ... }
. For C (and by extension C++) the changes aren't much more complicated:
#include <math.h>
unsigned char b[] = { 62, 232, 185, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 };
double d = 0.0;
for (int i = 11; i >= 0; --i) {
unsigned char k = b[i];
for (int j = 0; j != 8; ++j) {
d *= 2;
d += (k & 0x80) >> 7;
k <<= 1;
}
}
int scale = b[14];
d /= pow(10, scale);
if (b[15] >= 0x80) d = -d;
Upvotes: 5