Skip to content

Commit a4a51fe

Browse files
dmkexlab
authored andcommitted
pdu: add Is7BitEncodable() method
This method can help in input validation. Since Encode7Bit auto-substitutes unknown characters with '?', we cannot simply check whether decode(encode(input)) == input.
1 parent f08e6ce commit a4a51fe

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

pdu/7bit.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,41 @@ const (
2525
// ErrUnexpectedByte happens when someone tries to decode non GSM 7-bit encoded string.
2626
var ErrUnexpectedByte = errors.New("7bit decode: met an unexpected byte")
2727

28-
// Encode7Bit encodes the given UTF-8 text into GSM 7-bit (3GPP TS 23.038) encoding with packing.
28+
// Is7BitEncodable reports whether s can be encoded using GSM 7-bit
29+
// encoding with default alphabet, without replacing or omitting characters.
30+
func Is7BitEncodable(s string) bool {
31+
for _, r := range s {
32+
if i := gsmTable.Index(r); i < 0 {
33+
if gsmEscapes.to7Bit(r) == byte(unknown) {
34+
return false
35+
}
36+
}
37+
}
38+
return true
39+
}
40+
41+
// Encode7Bit encodes the given UTF-8 text into GSM 7-bit (3GPP TS 23.038)
42+
// encoding with packing. Invalid characters outside the 7-bit encoding
43+
// and shift table are replaced with "?".
2944
func Encode7Bit(str string) []byte {
3045
raw7 := make([]byte, 0, len(str))
3146
for _, r := range str {
32-
i := gsmTable.Index(r)
33-
if i < 0 {
47+
if i := gsmTable.Index(r); i >= 0 {
48+
raw7 = append(raw7, byte(i))
49+
} else {
3450
b := gsmEscapes.to7Bit(r)
35-
if b != byte(unknown) {
36-
raw7 = append(raw7, Esc, b)
37-
} else {
51+
if b == byte(unknown) {
3852
raw7 = append(raw7, b)
53+
} else {
54+
raw7 = append(raw7, Esc, b)
3955
}
40-
continue
4156
}
42-
raw7 = append(raw7, byte(i))
4357
}
4458
return pack7Bit(raw7)
4559
}
4660

47-
// Decode7Bit decodes the given GSM 7-bit packed octet data (3GPP TS 23.038) into a UTF-8 encoded string.
61+
// Decode7Bit decodes the given GSM 7-bit packed octet data (3GPP TS 23.038)
62+
// into an UTF-8 encoded string.
4863
func Decode7Bit(octets []byte) (str string, err error) {
4964
raw7 := unpack7Bit(octets)
5065
var escaped bool
@@ -188,8 +203,8 @@ var gsmEscapes = escapeTable{
188203
type runeTable [0x80]rune
189204

190205
func (rt *runeTable) Index(r rune) int {
191-
for i := range rt {
192-
if rt[i] == r {
206+
for i, c := range rt {
207+
if c == r {
193208
return i
194209
}
195210
}

pdu/7bit_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ import (
88
"github.com/xlab/at/util"
99
)
1010

11+
func TestIs7BitEncodable(t *testing.T) {
12+
t.Parallel()
13+
14+
for _, r := range gsmTable {
15+
ok := Is7BitEncodable(string(r))
16+
assert.True(t, ok, "'%c' should be 7bit-encodable, but wasn't", r)
17+
}
18+
for _, esc := range gsmEscapes {
19+
ok := Is7BitEncodable(string(esc.to))
20+
assert.True(t, ok, "'%c' should be 7bit-encodable, but wasn't", esc.to)
21+
}
22+
}
23+
1124
func TestEncode7Bit(t *testing.T) {
1225
t.Parallel()
1326

0 commit comments

Comments
 (0)