commit
65dca5de6e
17
unpack.go
17
unpack.go
|
@ -7,8 +7,10 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrInvalidString - Определение пользовательской ошибки для недопустимой строки.
|
||||||
var ErrInvalidString = errors.New("invalid string")
|
var ErrInvalidString = errors.New("invalid string")
|
||||||
|
|
||||||
|
// state - Тип-перечисление для представления состояния автомата.
|
||||||
type state int
|
type state int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -17,6 +19,7 @@ const (
|
||||||
number
|
number
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Unpack - Функция для распаковки строки в заданном формате.
|
||||||
func Unpack(str string) (string, error) {
|
func Unpack(str string) (string, error) {
|
||||||
var currentState state = start
|
var currentState state = start
|
||||||
var result strings.Builder
|
var result strings.Builder
|
||||||
|
@ -25,6 +28,7 @@ func Unpack(str string) (string, error) {
|
||||||
var runeArray = []rune(str)
|
var runeArray = []rune(str)
|
||||||
|
|
||||||
if len(runeArray) > 0 && unicode.IsDigit(runeArray[0]) {
|
if len(runeArray) > 0 && unicode.IsDigit(runeArray[0]) {
|
||||||
|
// Если первый символ является цифрой, возвращаем ошибку "недопустимой строки".
|
||||||
return "first rune is digit", ErrInvalidString
|
return "first rune is digit", ErrInvalidString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +41,7 @@ func Unpack(str string) (string, error) {
|
||||||
numOfRepeat, _ = strconv.Atoi(string(char))
|
numOfRepeat, _ = strconv.Atoi(string(char))
|
||||||
repStr, err := repeatRune(runeArray[i-1], numOfRepeat)
|
repStr, err := repeatRune(runeArray[i-1], numOfRepeat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Если функция repeatRune возвращает ошибку, удаляем последний символ из результата.
|
||||||
res := result.String()
|
res := result.String()
|
||||||
result.Reset()
|
result.Reset()
|
||||||
result.WriteString(res[0 : len(res)-1])
|
result.WriteString(res[0 : len(res)-1])
|
||||||
|
@ -45,16 +50,18 @@ func Unpack(str string) (string, error) {
|
||||||
} else if char == '\\' {
|
} else if char == '\\' {
|
||||||
currentState = escape
|
currentState = escape
|
||||||
} else {
|
} else {
|
||||||
currentState = start
|
|
||||||
result.WriteRune(char)
|
result.WriteRune(char)
|
||||||
|
currentState = start
|
||||||
}
|
}
|
||||||
case number:
|
case number:
|
||||||
if unicode.IsDigit(char) {
|
if unicode.IsDigit(char) {
|
||||||
|
// Если после цифры идет ещё одна цифра, возвращаем ошибку "недопустимой строки".
|
||||||
return "", ErrInvalidString
|
return "", ErrInvalidString
|
||||||
}
|
}
|
||||||
currentState = start
|
|
||||||
result.WriteRune(char)
|
result.WriteRune(char)
|
||||||
|
currentState = start
|
||||||
case escape:
|
case escape:
|
||||||
|
// Если текущий символ - обратный слэш, добавляем его в результат.
|
||||||
result.WriteRune(char)
|
result.WriteRune(char)
|
||||||
currentState = start
|
currentState = start
|
||||||
}
|
}
|
||||||
|
@ -65,12 +72,16 @@ func Unpack(str string) (string, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repeatRune - Функция для повторения символа заданное количество раз.
|
||||||
func repeatRune(char rune, numOfRepeat int) (string, error) {
|
func repeatRune(char rune, numOfRepeat int) (string, error) {
|
||||||
if numOfRepeat > 0 {
|
if numOfRepeat > 0 {
|
||||||
|
// Повторяем символ заданное количество раз и возвращаем строку.
|
||||||
return strings.Repeat(string(char), numOfRepeat-1), nil
|
return strings.Repeat(string(char), numOfRepeat-1), nil
|
||||||
}
|
}
|
||||||
if numOfRepeat == 0 {
|
if numOfRepeat == 0 {
|
||||||
|
// Если количество повторений равно нулю, возвращаем ошибку "нулевое повторение".
|
||||||
return "", errors.New("zero repeat")
|
return "", errors.New("zero repeat")
|
||||||
}
|
}
|
||||||
return "", nil
|
// Возвращаем пустую строку для отрицательных значений numOfRepeat.
|
||||||
|
return "", errors.New("negative repeat")
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ func TestUnpack(t *testing.T) {
|
||||||
{input: "a2", expected: "aa"},
|
{input: "a2", expected: "aa"},
|
||||||
{input: "aa", expected: "aa"},
|
{input: "aa", expected: "aa"},
|
||||||
{input: "a", expected: "a"},
|
{input: "a", expected: "a"},
|
||||||
|
{input: "日本語", expected: "日本語"},
|
||||||
|
{input: "日本語2", expected: "日本語語"},
|
||||||
{input: "d\n5abc", expected: "d\n\n\n\n\nabc"},
|
{input: "d\n5abc", expected: "d\n\n\n\n\nabc"},
|
||||||
{input: `qwe\4\5`, expected: `qwe45`},
|
{input: `qwe\4\5`, expected: `qwe45`},
|
||||||
{input: `qwe\45`, expected: `qwe44444`},
|
{input: `qwe\45`, expected: `qwe44444`},
|
||||||
|
|
Loading…
Reference in New Issue