Skip to content

Commit 57f256f

Browse files
committed
tmp
1 parent 377fd3d commit 57f256f

File tree

3 files changed

+71
-43
lines changed

3 files changed

+71
-43
lines changed

decimal/bcd.go

+38-24
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Package implements methods to encode and decode BCD.
2-
// BCD is a sequence of bytes representing decimal digits of the encoded number
3-
// (each byte has two decimal digits each encoded using 4-bit nibbles),
4-
// so byte >> 4 is the first digit and byte & 0x0f is the second digit. The
5-
// leftmost digit in the array is the most significant. The rightmost digit in
6-
// the array is the least significant.
2+
//
3+
// BCD (Binary-Coded Decimal) is a sequence of bytes representing decimal
4+
// digits of the encoded number (each byte has two decimal digits each encoded
5+
// using 4-bit nibbles), so byte >> 4 is the first digit and byte & 0x0f is the
6+
// second digit. The leftmost digit in the array is the most significant. The
7+
// rightmost digit in the array is the least significant.
8+
//
79
// The first byte of the BCD array contains the first digit of the number,
810
// represented as follows:
911
//
@@ -17,13 +19,19 @@
1719
// | 4 bits | 4 bits |
1820
// = the last digit = nibble
1921
//
22+
// The final nibble represents the number’s sign:
23+
//
24+
// 0x0a, 0x0c, 0x0e, 0x0f stand for plus,
25+
// 0x0b and 0x0d stand for minus.
26+
//
2027
// TODO: BitReader https://go.dev/play/p/Wyr_K9YAro
2128
package decimal
2229

2330
import (
2431
"errors"
25-
_ "fmt"
32+
"fmt"
2633
"strconv"
34+
_ "strings"
2735
)
2836

2937
var (
@@ -32,7 +40,7 @@ var (
3240
)
3341

3442
const decimalMaxDigits = 38 // Maximum decimal digits taken by a decimal representation.
35-
const mpScaleIdx = 0
43+
const mpScaleIdx = 0 // Index of byte with scale.
3644

3745
var mpDecimalSign = map[rune]byte{
3846
'+': 0x0a,
@@ -48,7 +56,7 @@ var mpIsDecimalNegative = map[byte]bool{
4856
0x0f: false,
4957
}
5058

51-
var hex_digit = map[rune]byte{
59+
var hexDigit = map[rune]byte{
5260
'1': 0x1,
5361
'2': 0x2,
5462
'3': 0x3,
@@ -69,31 +77,36 @@ func lowNibble(b byte) byte {
6977
return b & 0x0f
7078
}
7179

72-
func MPEncodeStringToBCD(buf string) []byte {
73-
scale := 0
74-
sign := '+'
75-
// TODO: The first nibble contains 0 if the decimal number has an even number of digits.
76-
nibbleIdx := 2 /* First nibble is for sign */
80+
// TODO: The first nibble contains 0 if the decimal number has an even number of digits.
81+
func MPEncodeStringToBCD(buf string) ([]byte, error) {
82+
sign := '+' // By default number is positive.
83+
/*
84+
if res := strings.HasPrefix(buf, "-"); res == true {
85+
sign = '-'
86+
}
87+
*/
88+
scale := 0 // By default number is integer.
89+
nibbleIdx := 2 // Number of a current nibble in a byte buffer.
7790
byteBuf := make([]byte, 1)
7891
for i, ch := range buf {
79-
// TODO: ignore leading zeroes
80-
// Check for sign in a first nibble.
92+
fmt.Printf("DEBUG: ch = %c\n", ch)
93+
// Check for sign in a first symbol.
8194
if (i == 0) && (ch == '-' || ch == '+') {
8295
sign = ch
96+
fmt.Printf("DEBUG: Sign is %c\n", sign)
8397
continue
8498
}
8599

86-
// Remember a number of digits after the decimal point.
100+
// Calculate a number of digits after the decimal point.
87101
if ch == '.' {
88102
scale = len(buf) - i - 1
103+
fmt.Printf("DEBUG: Scale is %d\n", scale)
89104
continue
90105
}
91106

92-
//digit := byte(ch) // TODO
93-
digit := hex_digit[ch]
94-
highNibble := nibbleIdx%2 != 0
107+
digit := hexDigit[ch]
95108
lowByte := len(byteBuf) - 1
96-
if highNibble {
109+
if nibbleIdx%2 != 0 {
97110
digit = digit << 4
98111
byteBuf = append(byteBuf, digit)
99112
} else {
@@ -103,19 +116,20 @@ func MPEncodeStringToBCD(buf string) []byte {
103116
byteBuf[lowByte] = byteBuf[lowByte] | digit
104117
}
105118
}
106-
//fmt.Printf("DEBUG: %x\n", byteBuf)
119+
fmt.Printf("DEBUG: idx == %d, buf %x\n", i, byteBuf)
107120
nibbleIdx += 1
108121
}
122+
fmt.Printf("DEBUG: final buf %x\n", byteBuf)
109123
if nibbleIdx%2 != 0 {
110124
byteBuf = append(byteBuf, mpDecimalSign[sign])
111125
} else {
112126
lowByte := len(byteBuf) - 1
113127
byteBuf[lowByte] = byteBuf[lowByte] | mpDecimalSign[sign]
114128
}
115129
byteBuf = append([]byte{byte(scale)}, byteBuf...)
116-
//fmt.Printf("DEBUG: Encoded byteBuf %x\n", byteBuf)
130+
fmt.Printf("DEBUG: Encoded byteBuf %x\n", byteBuf)
117131

118-
return byteBuf
132+
return byteBuf, nil
119133
}
120134

121135
func MPDecodeStringFromBCD(bcdBuf []byte) ([]string, error) {
@@ -131,7 +145,7 @@ func MPDecodeStringFromBCD(bcdBuf []byte) ([]string, error) {
131145

132146
// BCD buffer without a byte with scale.
133147
bcdBuf = bcdBuf[mpScaleIdx+1:]
134-
//fmt.Printf("DEBUG: BCDbuf without byte with scale %x\n", bcdBuf)
148+
fmt.Printf("DEBUG: BCDbuf without byte with scale %x\n", bcdBuf)
135149
length := len(bcdBuf)
136150
var digits []string
137151
for i, bcd_byte := range bcdBuf {

decimal/decimal.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ const decimal_extId = 1
2828
func encodeDecimal(e *msgpack.Encoder, v reflect.Value) error {
2929
number := v.Interface().(decimal.Decimal)
3030
dec := number.String()
31-
bcdBuf := MPEncodeStringToBCD(dec)
32-
_, err := e.Writer().Write(bcdBuf)
31+
bcdBuf, err := MPEncodeStringToBCD(dec)
32+
if err != nil {
33+
return err
34+
}
35+
_, err = e.Writer().Write(bcdBuf)
3336
if err != nil {
3437
return fmt.Errorf("msgpack: can't write bytes to encoder writer: %w", err)
3538
}
@@ -41,6 +44,8 @@ func decodeDecimal(d *msgpack.Decoder, v reflect.Value) error {
4144
var bytesCount int = 4 // FIXME
4245
b := make([]byte, bytesCount)
4346

47+
fmt.Printf("DEBUG: decodeDecimal buffer %x\n", b)
48+
4449
_, err := d.Buffered().Read(b)
4550
if err != nil {
4651
return fmt.Errorf("msgpack: can't read bytes on decimal decode: %w", err)

decimal/decimal_test.go

+26-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"log"
66
"os"
77
"reflect"
8-
"strings"
8+
_ "strings"
99
"testing"
1010
"time"
1111

@@ -144,16 +144,17 @@ var decimalBCD = []struct {
144144
numString string
145145
}{
146146
{[]byte{0x02, 0x01, 0x23, 0x4b}, "-12.34"},
147-
{[]byte{0x0, 0xa}, "0"}, // WRONG 00000a
147+
//{[]byte{0x0, 0xa}, "0"}, // WRONG 00000a
148148
//{[]byte{0x0, 0xb}, "-0"}, // WRONG 00000b
149-
//{[]byte{0x0, 0x1a}, "1"}, // WRONG 00010a
149+
{[]byte{0x0, 0x1a}, "1"}, // WRONG 00010a
150150
//{[]byte{0x0, 0x1b}, "-1"}, // WRONG 00010b
151151
//{[]byte{0x1, 0x1a}, "0.1"}, // WRONG 00010a
152152
//{[]byte{0x1, 0x1b}, "-0.1"}, // WRONG 00010b
153153
//{[]byte{0x25, 0x1a}, "0.0000000000000000000000000000000000001"}, // WRONG 25000000000000000000000000000000000000001a
154154
//{[]byte{0x25, 0x1b}, "-0.0000000000000000000000000000000000001"}, // WRONG 25000000000000000000000000000000000000001b
155155
//{[]byte{0x26, 0x1a}, "0.00000000000000000000000000000000000001"}, // WRONG 2600000000000000000000000000000000000000010a
156156
//{[]byte{0x26, 0x1b}, "-0.00000000000000000000000000000000000001"}, // WRONG 2600000000000000000000000000000000000000010b
157+
157158
//{[]byte{0x03, 0x01, 0x24, 0x01, 0x0c}, "0.000000000000000000000000000000000010"},
158159
// {[]byte{0xc70b010f0123456789000000000c}, "123.456789000000000"},
159160
// {[]byte{0xc70a010f02718281828459045c}, "2.718281828459045"},
@@ -169,9 +170,13 @@ var decimalBCD = []struct {
169170
func TestMPEncodeStringToBCD(t *testing.T) {
170171
for _, testcase := range decimalBCD {
171172
t.Run(testcase.numString, func(t *testing.T) {
172-
buf := MPEncodeStringToBCD(testcase.numString)
173+
buf, err := MPEncodeStringToBCD(testcase.numString)
174+
if err != nil {
175+
t.Fatalf("Failed to encode string with decimal to BCD: %s", err)
176+
177+
}
173178
if reflect.DeepEqual(buf, testcase.bcdBuf) != true {
174-
t.Fatalf("Failed to encode decimal %s to BCD (actual: '%x', expected '%x')", testcase.numString, buf, testcase.bcdBuf)
179+
t.Fatalf("Failed to encode string with decimal '%s' to BCD (actual: '%x', expected '%x')", testcase.numString, buf, testcase.bcdBuf)
175180
}
176181
})
177182
}
@@ -180,21 +185,25 @@ func TestMPEncodeStringToBCD(t *testing.T) {
180185
func TestMPDecodeStringFromBCD(t *testing.T) {
181186
for _, testcase := range decimalBCD {
182187
t.Run(testcase.numString, func(t *testing.T) {
183-
dec_expected, err := decimal.NewFromString(testcase.numString)
184-
if err != nil {
185-
t.Fatalf("Failed to encode string to decimal")
186-
}
187188
s, err := MPDecodeStringFromBCD(testcase.bcdBuf)
188189
if err != nil {
189-
t.Fatalf("Failed to decode decimal (%s) from BCD (%x) - '%x'", testcase.numString, testcase.bcdBuf, s)
190-
}
191-
dec_actual, err := decimal.NewFromString(strings.Join(s, ""))
192-
if err != nil {
193-
t.Fatalf("Failed to encode string to decimal")
194-
}
195-
if !dec_expected.Equal(dec_actual) {
196-
t.Fatalf("Failed to decode decimal (%s) from BCD (%x) - '%x'", testcase.numString, testcase.bcdBuf, s)
190+
t.Fatalf("Failed to decode BCD ('%x') to string with decimal (actual: '%s', expected '%s')", testcase.bcdBuf, s, testcase.numString)
197191
}
192+
193+
/*
194+
descStr := strings.Join(s, "")
195+
decActual, err := decimal.NewFromString()
196+
if err != nil {
197+
t.Fatalf("Failed to encode string ('%s') to decimal", decStr)
198+
}
199+
decExpected, err := decimal.NewFromString(testcase.numString)
200+
if err != nil {
201+
t.Fatalf("Failed to encode string to decimal")
202+
}
203+
if !decExpected.Equal(decActual) {
204+
t.Fatalf("Failed to decode decimal (%s) from BCD (%x) - '%x'", testcase.numString, testcase.bcdBuf, s)
205+
}
206+
*/
198207
})
199208
}
200209
}

0 commit comments

Comments
 (0)