diff --git a/data/codings.go b/data/codings.go index 64a5093..e4f5fe0 100644 --- a/data/codings.go +++ b/data/codings.go @@ -93,10 +93,15 @@ func (c *gsm7bit) Decode(data []byte) (string, error) { func (c *gsm7bit) DataCoding() byte { return GSM7BITCoding } func (c *gsm7bit) ShouldSplit(text string, octetLimit uint) (shouldSplit bool) { + runeSlice := []rune(text) + tLen := len(runeSlice) + escCharsLen := len(GetEscapeChars(runeSlice)) + regCharsLen := tLen - escCharsLen + bytesLen := regCharsLen + escCharsLen*2 if c.packed { - return uint((len(text)*7+7)/8) > octetLimit + return uint((bytesLen*7+7)/8) > octetLimit } else { - return uint(len(text)) > octetLimit + return uint(bytesLen) > octetLimit } } @@ -105,20 +110,33 @@ func (c *gsm7bit) EncodeSplit(text string, octetLimit uint) (allSeg [][]byte, er octetLimit = 134 } - allSeg = [][]byte{} - runeSlice := []rune(text) + bytes, err := c.Encode(text) + if err != nil { + return nil, err + } - fr, to := 0, int(octetLimit) - for fr < len(runeSlice) { - if to > len(runeSlice) { - to = len(runeSlice) + fr := uint(0) + to := uint(0) + for { + for to < uint(len(bytes)) { + inc := uint(1) + if bytes[to] == escapeSequence { + inc = 2 + } + + if to-fr+inc > octetLimit { + break + } + + to += inc } - seg, err := c.Encode(string(runeSlice[fr:to])) - if err != nil { - return nil, err + + if fr == to { + break } - allSeg = append(allSeg, seg) - fr, to = to, to+int(octetLimit) + + allSeg = append(allSeg, bytes[fr:to]) + fr = to } return diff --git a/data/codings_test.go b/data/codings_test.go index 12b8451..596abde 100644 --- a/data/codings_test.go +++ b/data/codings_test.go @@ -85,7 +85,10 @@ func TestShouldSplit(t *testing.T) { "": false, "1": false, "12312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311234121212": false, + "1231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123412121{": true, "123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112312312311231231231123123123112342212121": true, + "{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}1234": false, + "{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}{[]}123]": true, } splitter, _ := GSM7BIT.(Splitter) @@ -190,6 +193,77 @@ func TestSplit(t *testing.T) { }) } +func TestSplit_GSM7BIT(t *testing.T) { + require.EqualValues(t, 0o0, GSM7BIT.DataCoding()) + + /* + Total char count = 150, + Esc char count = 2, + Regular char count = 148, + Seg1 => 132-> ....{ + Seg2 => 18-> ....{ + Expected behaviour: Should not split in the middle of ESC chars + */ + t.Run("testSplit_EscEndOfSeg1_GSM7BIT", func(t *testing.T) { + testEncodingSplit(t, GSM7BIT, + 134, + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk[{eeeeeeeeeeeeeeeee", + []string{ + "6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b1b3c", + "1b286565656565656565656565656565656565", + }, + []string{ + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk[", + "{eeeeeeeeeeeeeeeee", + }) + }) + + /* + Total char count = 150, + Esc char count = 2, + Regular char count = 148, + Seg1 => 133-> ....{ + Seg2 => 17-> ....{ + Expected behaviour: Should not split in the middle of ESC chars + */ + t.Run("testSplit_EscBegOfSeg2_GSM7BIT", func(t *testing.T) { + testEncodingSplit(t, GSM7BIT, + 134, + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{{aaaaaaaaaaaaaaa", + []string{ + "61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", + "1b281b28616161616161616161616161616161", + }, + []string{ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "{{aaaaaaaaaaaaaaa", + }) + }) + + /* + Total char count = 193, + Esc char count = 75, + Regular char count = 118, + Seg1 => 119-> ....{ + Seg2 => 74-> ....{ + Expected behaviour: Should not split in the middle of ESC chars, + all segments are fully loaded + */ + t.Run("testSplit_FullyLoadedSegments_GSM7BIT", func(t *testing.T) { + testEncodingSplit(t, GSM7BIT, + 134, + "\\{[~€€€€~]}\\|^kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\f{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}llllllllllllll", + []string{ + "1b2f1b281b3c1b3d1b651b651b651b651b3d1b3e1b291b2f1b401b146b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b1b0a", + "1b281b3c1b3d1b2f1b651b401b141b0a1b2f1b3d1b3e1b291b281b3c1b3d1b2f1b651b401b141b0a1b2f1b3d1b3e1b291b281b3c1b3d1b2f1b651b401b141b0a1b2f1b3d1b3e1b291b281b3c1b3d1b2f1b651b401b141b0a1b2f1b3d1b3e1b291b281b3c1b3d1b2f1b651b401b141b0a1b2f1b3d1b3e1b296c6c6c6c6c6c6c6c6c6c6c6c6c6c", + }, + []string{ + "\\{[~€€€€~]}\\|^kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\f", + "{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}{[~\\€|^\f\\~]}llllllllllllll", + }) + }) +} + func TestSplit_GSM7BITPACKED(t *testing.T) { require.EqualValues(t, 0o0, GSM7BITPACKED.DataCoding())