// ScanEscape writes escaped sequence to buffer. func ScanEscape(scanner scanner.Scanner, buffer *bytes.Buffer) error { escapedRune, err := scanner.PeekRune() if err != nil { return err } scanner.NextRune() switch escapedRune { case '"': buffer.WriteString("\"") case '\\': buffer.WriteString("\\") case '/': buffer.WriteString("/") case 'b': buffer.WriteString("\b") case 'f': buffer.WriteString("\f") case 'n': buffer.WriteString("\n") case 'r': buffer.WriteString("\r") case 't': buffer.WriteString("\t") case 'u': unicodes, err := ReadUnicodeSequence(scanner) if err != nil { return err } buffer.WriteString(unicodes) default: return fmt.Errorf("%s is invalid escaped rune", string(escapedRune)) } return nil }
// ReadUnicodeSequence returns string. func ReadUnicodeSequence(scanner scanner.Scanner) (string, error) { codes := []uint16{} for { code, err := ReadUnicode(scanner) if err != nil { return "", err } codes = append(codes, code) maybeEscape, err := scanner.PeekRuneWithOffset(0) if err != nil { break } maybeUnicode, err := scanner.PeekRuneWithOffset(1) if err != nil { break } if maybeEscape != '\\' || maybeUnicode != 'u' { break } scanner.NextRune() scanner.NextRune() } return string(utf16.Decode(codes)), nil }
// ScanNumber returns string. func ScanNumber(scanner scanner.Scanner, firstRune rune) (string, error) { nam := NewNAMState() err := nam.Input(firstRune) if err != nil { return "", err } for { peekedRune, err := scanner.PeekRune() if err == io.EOF { nam.EOF() break } if err != nil { return "", err } err = nam.Input(peekedRune) if err != nil { return "", err } if nam.state != -1 { scanner.NextRune() } else { break } } if !nam.Finished() { return "", fmt.Errorf("Invalid number") } return nam.Result(), nil }
// ReadUnicode returns unicode. func ReadUnicode(scanner scanner.Scanner) (uint16, error) { var buffer bytes.Buffer for i := 0; i < 4; i++ { currentRune, err := scanner.NextRune() if err != nil { return 0, err } if unicode.IsDigit(currentRune) || currentRune == 'a' || currentRune == 'A' || currentRune == 'b' || currentRune == 'B' || currentRune == 'c' || currentRune == 'C' || currentRune == 'd' || currentRune == 'D' || currentRune == 'e' || currentRune == 'E' || currentRune == 'f' || currentRune == 'F' { buffer.WriteRune(currentRune) continue } return 0, fmt.Errorf("%s is valid unicode", currentRune) } result, err := strconv.ParseUint(buffer.String(), 16, 16) if err != nil { return 0, err } return uint16(result), nil }
// ScanString returns string. func ScanString(scanner scanner.Scanner) (string, error) { var buffer bytes.Buffer for { peekedRune, err := scanner.PeekRune() if err != nil { return "", err } if peekedRune == '"' { scanner.NextRune() break } if peekedRune != '\\' { scanner.NextRune() buffer.WriteRune(peekedRune) } else { scanner.NextRune() ScanEscape(scanner, &buffer) } } return buffer.String(), nil }