mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 01:02:25 -06:00 
			
		
		
		
	* Add SQLite support, fix un-thread-safe DB caches, small performance fixes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add SQLite licenses to README Signed-off-by: kim (grufwub) <grufwub@gmail.com> * appease the linter, and fix my dumbass-ery Signed-off-by: kim (grufwub) <grufwub@gmail.com> * make requested changes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add back comment Signed-off-by: kim (grufwub) <grufwub@gmail.com>
		
			
				
	
	
		
			156 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package shellquote
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"errors"
 | 
						|
	"strings"
 | 
						|
	"unicode/utf8"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	UnterminatedSingleQuoteError = errors.New("Unterminated single-quoted string")
 | 
						|
	UnterminatedDoubleQuoteError = errors.New("Unterminated double-quoted string")
 | 
						|
	UnterminatedEscapeError      = errors.New("Unterminated backslash-escape")
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	splitChars        = " \n\t"
 | 
						|
	singleChar        = '\''
 | 
						|
	doubleChar        = '"'
 | 
						|
	escapeChar        = '\\'
 | 
						|
	doubleEscapeChars = "$`\"\n\\"
 | 
						|
)
 | 
						|
 | 
						|
// Split splits a string according to /bin/sh's word-splitting rules. It
 | 
						|
// supports backslash-escapes, single-quotes, and double-quotes. Notably it does
 | 
						|
// not support the $'' style of quoting. It also doesn't attempt to perform any
 | 
						|
// other sort of expansion, including brace expansion, shell expansion, or
 | 
						|
// pathname expansion.
 | 
						|
//
 | 
						|
// If the given input has an unterminated quoted string or ends in a
 | 
						|
// backslash-escape, one of UnterminatedSingleQuoteError,
 | 
						|
// UnterminatedDoubleQuoteError, or UnterminatedEscapeError is returned.
 | 
						|
func Split(input string) (words []string, err error) {
 | 
						|
	var buf bytes.Buffer
 | 
						|
	words = make([]string, 0)
 | 
						|
 | 
						|
	for len(input) > 0 {
 | 
						|
		// skip any splitChars at the start
 | 
						|
		c, l := utf8.DecodeRuneInString(input)
 | 
						|
		if strings.ContainsRune(splitChars, c) {
 | 
						|
			input = input[l:]
 | 
						|
			continue
 | 
						|
		} else if c == escapeChar {
 | 
						|
			// Look ahead for escaped newline so we can skip over it
 | 
						|
			next := input[l:]
 | 
						|
			if len(next) == 0 {
 | 
						|
				err = UnterminatedEscapeError
 | 
						|
				return
 | 
						|
			}
 | 
						|
			c2, l2 := utf8.DecodeRuneInString(next)
 | 
						|
			if c2 == '\n' {
 | 
						|
				input = next[l2:]
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		var word string
 | 
						|
		word, input, err = splitWord(input, &buf)
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		words = append(words, word)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func splitWord(input string, buf *bytes.Buffer) (word string, remainder string, err error) {
 | 
						|
	buf.Reset()
 | 
						|
 | 
						|
raw:
 | 
						|
	{
 | 
						|
		cur := input
 | 
						|
		for len(cur) > 0 {
 | 
						|
			c, l := utf8.DecodeRuneInString(cur)
 | 
						|
			cur = cur[l:]
 | 
						|
			if c == singleChar {
 | 
						|
				buf.WriteString(input[0 : len(input)-len(cur)-l])
 | 
						|
				input = cur
 | 
						|
				goto single
 | 
						|
			} else if c == doubleChar {
 | 
						|
				buf.WriteString(input[0 : len(input)-len(cur)-l])
 | 
						|
				input = cur
 | 
						|
				goto double
 | 
						|
			} else if c == escapeChar {
 | 
						|
				buf.WriteString(input[0 : len(input)-len(cur)-l])
 | 
						|
				input = cur
 | 
						|
				goto escape
 | 
						|
			} else if strings.ContainsRune(splitChars, c) {
 | 
						|
				buf.WriteString(input[0 : len(input)-len(cur)-l])
 | 
						|
				return buf.String(), cur, nil
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if len(input) > 0 {
 | 
						|
			buf.WriteString(input)
 | 
						|
			input = ""
 | 
						|
		}
 | 
						|
		goto done
 | 
						|
	}
 | 
						|
 | 
						|
escape:
 | 
						|
	{
 | 
						|
		if len(input) == 0 {
 | 
						|
			return "", "", UnterminatedEscapeError
 | 
						|
		}
 | 
						|
		c, l := utf8.DecodeRuneInString(input)
 | 
						|
		if c == '\n' {
 | 
						|
			// a backslash-escaped newline is elided from the output entirely
 | 
						|
		} else {
 | 
						|
			buf.WriteString(input[:l])
 | 
						|
		}
 | 
						|
		input = input[l:]
 | 
						|
	}
 | 
						|
	goto raw
 | 
						|
 | 
						|
single:
 | 
						|
	{
 | 
						|
		i := strings.IndexRune(input, singleChar)
 | 
						|
		if i == -1 {
 | 
						|
			return "", "", UnterminatedSingleQuoteError
 | 
						|
		}
 | 
						|
		buf.WriteString(input[0:i])
 | 
						|
		input = input[i+1:]
 | 
						|
		goto raw
 | 
						|
	}
 | 
						|
 | 
						|
double:
 | 
						|
	{
 | 
						|
		cur := input
 | 
						|
		for len(cur) > 0 {
 | 
						|
			c, l := utf8.DecodeRuneInString(cur)
 | 
						|
			cur = cur[l:]
 | 
						|
			if c == doubleChar {
 | 
						|
				buf.WriteString(input[0 : len(input)-len(cur)-l])
 | 
						|
				input = cur
 | 
						|
				goto raw
 | 
						|
			} else if c == escapeChar {
 | 
						|
				// bash only supports certain escapes in double-quoted strings
 | 
						|
				c2, l2 := utf8.DecodeRuneInString(cur)
 | 
						|
				cur = cur[l2:]
 | 
						|
				if strings.ContainsRune(doubleEscapeChars, c2) {
 | 
						|
					buf.WriteString(input[0 : len(input)-len(cur)-l-l2])
 | 
						|
					if c2 == '\n' {
 | 
						|
						// newline is special, skip the backslash entirely
 | 
						|
					} else {
 | 
						|
						buf.WriteRune(c2)
 | 
						|
					}
 | 
						|
					input = cur
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return "", "", UnterminatedDoubleQuoteError
 | 
						|
	}
 | 
						|
 | 
						|
done:
 | 
						|
	return buf.String(), input, nil
 | 
						|
}
 |