status-go/vendor/github.com/pion/sdp/v3/base_lexer.go

217 lines
3.4 KiB
Go
Raw Normal View History

2024-06-05 20:10:03 +00:00
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
2022-03-10 09:44:48 +00:00
package sdp
import (
"errors"
"fmt"
"io"
2024-05-15 23:15:00 +00:00
"strconv"
2022-03-10 09:44:48 +00:00
)
var errDocumentStart = errors.New("already on document start")
type syntaxError struct {
s string
i int
}
func (e syntaxError) Error() string {
if e.i < 0 {
e.i = 0
}
2024-05-15 23:15:00 +00:00
return fmt.Sprintf("sdp: syntax error at pos %d: %s", e.i, strconv.QuoteToASCII(e.s[e.i:e.i+1]))
2022-03-10 09:44:48 +00:00
}
type baseLexer struct {
2024-06-05 20:10:03 +00:00
value string
2022-03-10 09:44:48 +00:00
pos int
}
func (l baseLexer) syntaxError() error {
2024-06-05 20:10:03 +00:00
return syntaxError{s: l.value, i: l.pos - 1}
2022-03-10 09:44:48 +00:00
}
func (l *baseLexer) unreadByte() error {
if l.pos <= 0 {
return errDocumentStart
}
l.pos--
return nil
}
func (l *baseLexer) readByte() (byte, error) {
if l.pos >= len(l.value) {
return byte(0), io.EOF
}
ch := l.value[l.pos]
l.pos++
return ch, nil
}
func (l *baseLexer) nextLine() error {
for {
ch, err := l.readByte()
2024-05-15 23:15:00 +00:00
if errors.Is(err, io.EOF) {
2022-03-10 09:44:48 +00:00
return nil
} else if err != nil {
return err
}
if !isNewline(ch) {
return l.unreadByte()
}
}
}
func (l *baseLexer) readWhitespace() error {
for {
ch, err := l.readByte()
2024-05-15 23:15:00 +00:00
if errors.Is(err, io.EOF) {
2022-03-10 09:44:48 +00:00
return nil
} else if err != nil {
return err
}
if !isWhitespace(ch) {
return l.unreadByte()
}
}
}
func (l *baseLexer) readUint64Field() (i uint64, err error) {
for {
ch, err := l.readByte()
2024-05-15 23:15:00 +00:00
if errors.Is(err, io.EOF) && i > 0 {
2022-03-10 09:44:48 +00:00
break
} else if err != nil {
return i, err
}
if isNewline(ch) {
if err := l.unreadByte(); err != nil {
return i, err
}
break
}
if isWhitespace(ch) {
if err := l.readWhitespace(); err != nil {
return i, err
}
break
}
switch ch {
case '0':
i *= 10
case '1':
i = i*10 + 1
case '2':
i = i*10 + 2
case '3':
i = i*10 + 3
case '4':
i = i*10 + 4
case '5':
i = i*10 + 5
case '6':
i = i*10 + 6
case '7':
i = i*10 + 7
case '8':
i = i*10 + 8
case '9':
i = i*10 + 9
default:
return i, l.syntaxError()
}
}
return i, nil
}
// Returns next field on this line or empty string if no more fields on line
func (l *baseLexer) readField() (string, error) {
start := l.pos
2024-05-15 23:15:00 +00:00
var stop int
2022-03-10 09:44:48 +00:00
for {
stop = l.pos
ch, err := l.readByte()
2024-05-15 23:15:00 +00:00
if errors.Is(err, io.EOF) && stop > start {
2022-03-10 09:44:48 +00:00
break
} else if err != nil {
return "", err
}
if isNewline(ch) {
if err := l.unreadByte(); err != nil {
return "", err
}
break
}
if isWhitespace(ch) {
if err := l.readWhitespace(); err != nil {
return "", err
}
break
}
}
2024-06-05 20:10:03 +00:00
return l.value[start:stop], nil
2022-03-10 09:44:48 +00:00
}
// Returns symbols until line end
func (l *baseLexer) readLine() (string, error) {
start := l.pos
trim := 1
for {
ch, err := l.readByte()
if err != nil {
return "", err
}
if ch == '\r' {
trim++
}
if ch == '\n' {
2024-06-05 20:10:03 +00:00
return l.value[start : l.pos-trim], nil
2022-03-10 09:44:48 +00:00
}
}
}
2024-06-05 20:10:03 +00:00
func (l *baseLexer) readType() (byte, error) {
2022-03-10 09:44:48 +00:00
for {
2024-06-05 20:10:03 +00:00
firstByte, err := l.readByte()
2022-03-10 09:44:48 +00:00
if err != nil {
2024-06-05 20:10:03 +00:00
return 0, err
2022-03-10 09:44:48 +00:00
}
2024-06-05 20:10:03 +00:00
if isNewline(firstByte) {
2022-03-10 09:44:48 +00:00
continue
}
2024-06-05 20:10:03 +00:00
secondByte, err := l.readByte()
2022-03-10 09:44:48 +00:00
if err != nil {
2024-06-05 20:10:03 +00:00
return 0, err
2022-03-10 09:44:48 +00:00
}
2024-06-05 20:10:03 +00:00
if secondByte != '=' {
return firstByte, l.syntaxError()
2022-03-10 09:44:48 +00:00
}
2024-06-05 20:10:03 +00:00
return firstByte, nil
2022-03-10 09:44:48 +00:00
}
}
func isNewline(ch byte) bool { return ch == '\n' || ch == '\r' }
func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' }
func anyOf(element string, data ...string) bool {
for _, v := range data {
if element == v {
return true
}
}
return false
}