Skip to content

Instantly share code, notes, and snippets.

@sebmarkbage
Created June 15, 2010 18:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebmarkbage/439514 to your computer and use it in GitHub Desktop.
Save sebmarkbage/439514 to your computer and use it in GitHub Desktop.
public static Messages.Decimal BuildDecimal(decimal d)
{
int[] bits = decimal.GetBits(d.Value);
if (bits[2] != 0 || bits[1] < 0) throw new Exception("Unrepresentable decimal number. Out of range.");
long value = (((long)bits[1]) << 32) | ((long)bits[0] & 0xFFFFFFFFL);
if ((bits[3] & 0x80000000) != 0) value = -value;
uint scale = ((uint)bits[3] >> 16) & 0xF;
var builder = Messages.Decimal.CreateBuilder();
builder.SetValue(value);
if (scale != 0) builder.SetScale(scale);
return builder.Build();
}
public static decimal ParseDecimal(Messages.Decimal d)
{
if (!d.HasValue) throw new Exception("Expected value.");
uint scale = d.Scale;
if (scale > 28) throw new Exception("Invalid scale.");
long value = d.Value;
if (value < 0) value = -value;
int[] bits = new int[] {
(int)(value & 0xFFFFFFFFL),
(int)((value >> 32) & 0xFFFFFFFFL),
0,
(((int)scale & 0x1F) << 16) | ((int)((d.Value >> 32) & 0x80000000))
};
return new decimal(bits);
}
public static Proto.Decimal buildDecimal(BigDecimal d)
{
if (d == null) return null;
BigInteger value = d.unscaledValue();
if (value.compareTo(MAX_INT) > 0 || value.compareTo(MIN_INT) < 0)
throw new RuntimeException("Unrepresentable decimal number. Out of range.");
Proto.Decimal.Builder builder = Proto.Decimal.newBuilder();
builder.setValue(value.longValue());
if (d.scale() != 0) builder.setScale(d.scale());
return builder.build();
}
public static BigDecimal parseDecimal(Proto.Decimal d)
{
if (!d.hasValue()) throw new RuntimeException("Expected a scale.");
return BigDecimal.valueOf(d.getValue(), d.hasScale() ? d.getScale() : 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment