Exemplo n.º 1
0
        /// <inheritdoc />
        public override int ValidateAndGetLength(decimal value, NpgsqlParameter?parameter)
        {
            var groupCount = 0;
            var raw        = new DecimalRaw(value);

            if (raw.Low != 0 || raw.Mid != 0 || raw.High != 0)
            {
                uint remainder  = default;
                var  scaleChunk = raw.Scale % MaxGroupScale;
                if (scaleChunk > 0)
                {
                    var divisor    = DecimalRaw.Powers10[scaleChunk];
                    var multiplier = DecimalRaw.Powers10[MaxGroupScale - scaleChunk];
                    remainder = DecimalRaw.Divide(ref raw, divisor) * multiplier;
                }

                while (remainder == 0)
                {
                    remainder = DecimalRaw.Divide(ref raw, MaxGroupSize);
                }

                groupCount++;

                while (raw.Low != 0 || raw.Mid != 0 || raw.High != 0)
                {
                    DecimalRaw.Divide(ref raw, MaxGroupSize);
                    groupCount++;
                }
            }

            return(4 * sizeof(short) + groupCount * sizeof(short));
        }
Exemplo n.º 2
0
        public override void Write(decimal value, NpgsqlWriteBuffer buf, NpgsqlParameter parameter)
        {
            var raw             = Unsafe.As <decimal, DecimalRaw>(ref value);
            var scaleDifference = MoneyScale - raw.Scale;

            if (scaleDifference > 0)
            {
                DecimalRaw.Multiply(ref raw, DecimalRaw.Powers10[scaleDifference]);
            }
            else
            {
                while (scaleDifference < 0)
                {
                    var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, -scaleDifference);
                    DecimalRaw.Divide(ref raw, DecimalRaw.Powers10[scaleChunk]);
                    scaleDifference -= scaleChunk;
                }
            }

            var result = (long)raw.Mid << 32 | (long)raw.Low;

            if (raw.Negative)
            {
                result = -result;
            }
            buf.WriteInt64(result);
        }
Exemplo n.º 3
0
        public override decimal Read(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription = null)
        {
            var result = new DecimalRaw(buf.ReadInt64())
            {
                Scale = MoneyScale
            };

            return(Unsafe.As <DecimalRaw, decimal>(ref result));
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public override void Write(decimal value, NpgsqlWriteBuffer buf, NpgsqlParameter?parameter)
        {
            var          weight     = 0;
            var          groupCount = 0;
            Span <short> groups     = stackalloc short[MaxGroupCount];

            var raw = new DecimalRaw(value);

            if (raw.Low != 0 || raw.Mid != 0 || raw.High != 0)
            {
                var scale = raw.Scale;
                weight = -scale / MaxGroupScale - 1;

                uint remainder;
                var  scaleChunk = scale % MaxGroupScale;
                if (scaleChunk > 0)
                {
                    var divisor    = DecimalRaw.Powers10[scaleChunk];
                    var multiplier = DecimalRaw.Powers10[MaxGroupScale - scaleChunk];
                    remainder = DecimalRaw.Divide(ref raw, divisor) * multiplier;

                    if (remainder != 0)
                    {
                        weight--;
                        goto WriteGroups;
                    }
                }

                while ((remainder = DecimalRaw.Divide(ref raw, MaxGroupSize)) == 0)
                {
                    weight++;
                }

WriteGroups:
                groups[groupCount++] = (short)remainder;

                while (raw.Low != 0 || raw.Mid != 0 || raw.High != 0)
                {
                    groups[groupCount++] = (short)DecimalRaw.Divide(ref raw, MaxGroupSize);
                }
            }

            buf.WriteInt16(groupCount);
            buf.WriteInt16(groupCount + weight);
            buf.WriteInt16(raw.Negative ? SignNegative : SignPositive);
            buf.WriteInt16(raw.Scale);

            while (groupCount > 0)
            {
                buf.WriteInt16(groups[--groupCount]);
            }
        }
Exemplo n.º 5
0
        public override void Write(decimal value, NpgsqlWriteBuffer buf, NpgsqlParameter parameter)
        {
            var raw             = Unsafe.As <decimal, DecimalRaw>(ref value);
            var scaleDifference = MoneyScale - raw.Scale;

            if (scaleDifference > 0)
            {
                DecimalRaw.Multiply(ref raw, DecimalRaw.Powers10[scaleDifference]);
            }
            else
            {
                value = Math.Round(value, MoneyScale, MidpointRounding.AwayFromZero);
                raw   = Unsafe.As <decimal, DecimalRaw>(ref value);
            }

            var result = (long)raw.Mid << 32 | (long)raw.Low;

            if (raw.Negative)
            {
                result = -result;
            }
            buf.WriteInt64(result);
        }
Exemplo n.º 6
0
        /// <inheritdoc />
        public override decimal Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var result = new DecimalRaw();
            var groups = buf.ReadInt16();
            var weight = buf.ReadInt16() - groups + 1;
            var sign   = buf.ReadUInt16();

            if (sign == SignNan)
            {
                throw new InvalidCastException("Numeric NaN not supported by System.Decimal");
            }

            if (sign == SignNegative)
            {
                DecimalRaw.Negate(ref result);
            }

            var scale = buf.ReadInt16();

            if (scale < 0 is var exponential && exponential)
            {
                scale = (short)(-scale);
            }
Exemplo n.º 7
0
        /// <inheritdoc />
        public override decimal Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var result = new DecimalRaw();
            var groups = buf.ReadInt16();
            var weight = buf.ReadInt16() - groups + 1;
            var sign   = buf.ReadUInt16();

            if (sign == SignNan)
            {
                throw new InvalidCastException("Numeric NaN not supported by System.Decimal");
            }

            if (sign == SignNegative)
            {
                DecimalRaw.Negate(ref result);
            }

            var scale = buf.ReadInt16();

            if (scale > MaxDecimalScale)
            {
                throw new OverflowException("Numeric value does not fit in a System.Decimal");
            }

            result.Scale = scale;

            var scaleDifference = scale + weight * MaxGroupScale;

            if (groups == MaxGroupCount)
            {
                while (groups-- > 1)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                var group     = buf.ReadUInt16();
                var groupSize = DecimalRaw.Powers10[-scaleDifference];
                if (group % groupSize != 0)
                {
                    throw new OverflowException("Numeric value does not fit in a System.Decimal");
                }

                DecimalRaw.Multiply(ref result, MaxGroupSize / groupSize);
                DecimalRaw.Add(ref result, group / groupSize);
            }
            else
            {
                while (groups-- > 0)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                if (scaleDifference < 0)
                {
                    DecimalRaw.Divide(ref result, DecimalRaw.Powers10[-scaleDifference]);
                }
                else
                {
                    while (scaleDifference > 0)
                    {
                        var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, scaleDifference);
                        DecimalRaw.Multiply(ref result, DecimalRaw.Powers10[scaleChunk]);
                        scaleDifference -= scaleChunk;
                    }
                }
            }
            return(result.Value);
        }