// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package sdp

import (
	
	
	
	
)

var errDocumentStart = errors.New("already on document start")

type syntaxError struct {
	s string
	i int
}

func ( syntaxError) () string {
	if .i < 0 {
		.i = 0
	}

	return fmt.Sprintf("sdp: syntax error at pos %d: %s", .i, strconv.QuoteToASCII(.s[.i:.i+1]))
}

type baseLexer struct {
	value string
	pos   int
}

func ( baseLexer) () error {
	return syntaxError{s: .value, i: .pos - 1}
}

func ( *baseLexer) () error {
	if .pos <= 0 {
		return errDocumentStart
	}
	.pos--

	return nil
}

func ( *baseLexer) () (byte, error) {
	if .pos >= len(.value) {
		return byte(0), io.EOF
	}
	 := .value[.pos]
	.pos++

	return , nil
}

func ( *baseLexer) () error {
	for {
		,  := .readByte()
		if errors.Is(, io.EOF) {
			return nil
		} else if  != nil {
			return 
		}
		if !isNewline() {
			return .unreadByte()
		}
	}
}

func ( *baseLexer) () error { //notlint:cyclop
	for {
		,  := .readByte()
		if errors.Is(, io.EOF) {
			return nil
		} else if  != nil {
			return 
		}
		if !isWhitespace() {
			return .unreadByte()
		}
	}
}

func ( *baseLexer) () ( uint64,  error) { //nolint:cyclop
	for {
		,  := .readByte()
		if errors.Is(, io.EOF) &&  > 0 {
			break
		} else if  != nil {
			return , 
		}

		if isNewline() {
			if  := .unreadByte();  != nil {
				return , 
			}

			break
		}

		if isWhitespace() {
			if  := .readWhitespace();  != nil {
				return , 
			}

			break
		}

		switch  {
		case '0':
			 *= 10
		case '1':
			 = *10 + 1
		case '2':
			 = *10 + 2
		case '3':
			 = *10 + 3
		case '4':
			 = *10 + 4
		case '5':
			 = *10 + 5
		case '6':
			 = *10 + 6
		case '7':
			 = *10 + 7
		case '8':
			 = *10 + 8
		case '9':
			 = *10 + 9
		default:
			return , .syntaxError()
		}
	}

	return , nil
}

// Returns next field on this line or empty string if no more fields on line.
func ( *baseLexer) () (string, error) {
	 := .pos
	var  int
	for {
		 = .pos
		,  := .readByte()
		if errors.Is(, io.EOF) &&  >  {
			break
		} else if  != nil {
			return "", 
		}

		if isNewline() {
			if  := .unreadByte();  != nil {
				return "", 
			}

			break
		}

		if isWhitespace() {
			if  := .readWhitespace();  != nil {
				return "", 
			}

			break
		}
	}

	return .value[:], nil
}

// Returns symbols until line end.
func ( *baseLexer) () (string, error) {
	 := .pos
	 := 1
	for {
		,  := .readByte()
		if  != nil {
			return "", 
		}
		if  == '\r' {
			++
		}
		if  == '\n' {
			return .value[ : .pos-], nil
		}
	}
}

func ( *baseLexer) () (byte, error) {
	for {
		,  := .readByte()
		if  != nil {
			return 0, 
		}

		if isNewline() {
			continue
		}

		,  := .readByte()
		if  != nil {
			return 0, 
		}

		if  != '=' {
			return , .syntaxError()
		}

		return , nil
	}
}

func isNewline( byte) bool { return  == '\n' ||  == '\r' }

func isWhitespace( byte) bool { return  == ' ' ||  == '\t' }

func anyOf( string,  ...string) bool {
	for ,  := range  {
		if  ==  {
			return true
		}
	}

	return false
}