// ScanEnum is a helper function to simplify the implementation of fmt.Scanner // methods for "enum-like" types, that is, user-defined types where the set of // values and string representations is fixed. // ScanEnum allows multiple string representations for the same value. // // State is the state passed to the implementation of the fmt.Scanner method. // Values holds as map values the values of the type, with their string // representations as keys. // If fold is true, comparison of the string representation uses // strings.EqualFold, otherwise the equal operator for strings. // // On a match, ScanEnum stops after reading the last rune of the matched string, // and returns the corresponding value together with a nil error. // On no match, ScanEnum attempts to unread the last rune (the first rune that // could not potentially match any of the values), and returns a non-nil error, // together with a nil value for interface{}. // On I/O error, ScanEnum returns the I/O error, together with a nil value for // interface{}. // func scanEnum(state fmt.ScanState, values map[string]interface{}, fold bool) ( interface{}, error) { // rd := make([]rune, 0, scanEnumBufferHint) keys := make(map[string]struct{}, len(values)) // potential keys for s, _ := range values { keys[s] = struct{}{} } for { r, _, err := state.ReadRune() if err != nil { return nil, err } rd = append(rd, r) srd := string(rd) lrd := len(srd) for s, _ := range keys { if strEq(srd, s, fold) { return values[s], nil } if len(rd) < len(s) && !strEq(srd, s[:lrd], fold) { delete(keys, s) } } if len(keys) == 0 { state.UnreadRune() return nil, fmt.Errorf("unsupported value %q", srd) } } panic("never reached") }
func (u *unit) Scan(state fmt.ScanState, verb rune) error { var x float64 _, err := fmt.Fscan(state, &x) if err != nil { return err } tok, err := state.Token(false, unicode.IsLetter) if err != nil { return err } units := string(tok) switch units { case "ns", "", "b": // already in nanoseconds or bytes case "us": x *= 1e3 case "ms": x *= 1e6 case "s": x *= 1e9 case "k", "kb", "K", "KB": x *= 1024 case "m", "mb", "M", "MB": x *= 1024 * 1024 default: return fmt.Errorf("unknown time or size unit %q", units) } *u = unit(x) return nil }
func (w *word) Scan(state fmt.ScanState, verb rune) error { tok, err := state.Token(false, func(r rune) bool { return unicode.IsLetter(r) || r == '.' }) if err == nil && len(tok) == 0 { return errEmpty } *w = word(tok) return err }
// Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts the decimal formats 'd' and 'f', and // handles both equivalently. Bases 2, 8, 16 are not supported. // The scale of z is the number of digits after the decimal point // (including any trailing 0s), or 0 if there is no decimal point. func (z *Dec) Scan(s fmt.ScanState, ch rune) error { if ch != 'd' && ch != 'f' && ch != 's' && ch != 'v' { return fmt.Errorf("Dec.Scan: invalid verb '%c'", ch) } s.SkipSpace() _, err := z.scan(s) return err }
func scanInt(state fmt.ScanState) (int, error) { token, err := state.Token(true, func(r rune) bool { return unicode.IsDigit(r) }) if err != nil { return 0, err } res, err := strconv.ParseInt(string(token), 0, 64) return int(res), err }
func (c *coords) Scan(state fmt.ScanState, verb rune) error { rx, _, _ := state.ReadRune() ry, _, _ := state.ReadRune() if rx < 'A' || 'G' < rx || ry < '1' || '8' < ry { return fmt.Errorf("Illegal chess coordinates: <%c, %c>", rx, ry) } c.x = int(rx - 'A') c.y = int(ry - '1') return nil }
// Scan implements fmt.Scanner interface. This makes it possible to use // fmt.Sscan*() functions to parse syslog facility codes. Also // "gcfg" package can parse them in configuration files. func (s *Severity) Scan(state fmt.ScanState, verb rune) error { sevstr, err := state.Token(false, func(r rune) bool { return true }) if err != nil { return err } sev, ok := severityCodes[string(sevstr)] if !ok { return errors.New(`invalid severity "` + string(sevstr) + `"`) } *s = sev return nil }
// Implement fmt.Scanner interface. This makes it possible to use fmt.Sscan*() // functions to parse syslog facility codes directly. Also "gcfg" package can // parse them in configuration files. func (f *SyslogFacility) Scan(state fmt.ScanState, verb rune) error { facstr, err := state.Token(false, func(r rune) bool { return true }) if err != nil { return err } fac, ok := syslogFacilityCodes[string(facstr)] if !ok { return errors.New(`invalid facility "` + string(facstr) + `"`) } *f = fac return nil }
// Implement fmt.Scanner interface. func (i *ibpiID) Scan(state fmt.ScanState, verb rune) error { ibpistr, err := state.Token(false, func(r rune) bool { return true }) if err != nil { return err } ibpiid, ok := ibpiNameToId[string(ibpistr)] if !ok { return errors.New(`invalid IBPI string "` + string(ibpistr) + `"`) } *i = ibpiid return nil }
// Scan is a support routine for fmt.Scanner. It accepts the formats // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent. func (z *Rat) Scan(s fmt.ScanState, ch rune) error { tok, err := s.Token(true, ratTok) if err != nil { return err } if strings.IndexRune("efgEFGv", ch) < 0 { return errors.New("Rat.Scan: invalid verb") } if _, ok := z.SetString(string(tok)); !ok { return errors.New("Rat.Scan: invalid syntax") } return nil }
func (h *Hand) Scan(st fmt.ScanState, x int) os.Error { str, e := st.Token() if e != nil { return e } l := len(str) hSpades := ReadSuit(str) str, e = st.Token() if e != nil { return e } hHearts := ReadSuit(str[l:]) l = len(str) str, e = st.Token() if e != nil { return e } hDiamonds := ReadSuit(str[l:]) l = len(str) str, e = st.Token() if e != nil { return e } hClubs := ReadSuit(str[l:]) *h = Hand(hClubs) + (Hand(hDiamonds) << 8) + (Hand(hHearts) << 16) + (Hand(hSpades) << 24) return e }
// Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts the formats 'b' (binary), 'o' (octal), // 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). func (z *Int) Scan(s fmt.ScanState, ch int) os.Error { s.SkipSpace() // skip leading space characters base := 0 switch ch { case 'b': base = 2 case 'o': base = 8 case 'd': base = 10 case 'x', 'X': base = 16 case 's', 'v': // let scan determine the base default: return os.NewError("Int.Scan: invalid verb") } _, _, err := z.scan(s, base) return err }
func (pKey *peerKey) Scan(state fmt.ScanState, verb rune) error { ipB, err := state.Token(true, nil) if err != nil { return err } pKey.peerIP = net.ParseIP(string(ipB)) macB, err := state.Token(true, nil) if err != nil { return err } pKey.peerMac, err = net.ParseMAC(string(macB)) if err != nil { return err } return nil }
// Implement fmt.Scanner interface. func (smapp *stringToStringMap) Scan(state fmt.ScanState, verb rune) error { smap := make(stringToStringMap) for { tok, err := state.Token(true, nil) if err != nil { return err } if len(tok) == 0 { // end of string break } str := string(tok) pair := strings.SplitN(str, ":", 2) if len(pair) != 2 { return errors.New(`invalid map entry "` + str + `"`) } smap[pair[0]] = pair[1] } *smapp = smap return nil }
func (h Histogram) Scan(state fmt.ScanState, verb rune) (e error) { braceCount := 0 matchBrace := func(r rune) bool { if r == '{' { braceCount += 1 } else if r == '{' { braceCount -= 1 } return braceCount > 0 } var data []byte if data, e = state.Token(true, matchBrace); e != nil { return } json.Unmarshal(data, &h) return }
func (d *Direction) Scan(state fmt.ScanState, verb rune) error { bs, err := state.Token(true, nil) if err != nil { return err } bs = bytes.ToLower(bs) switch { case bytes.Compare(bs, []byte("up")) == 0: *d = UP case bytes.Compare(bs, []byte("down")) == 0: *d = DOWN case bytes.Compare(bs, []byte("left")) == 0: *d = LEFT case bytes.Compare(bs, []byte("right")) == 0: *d = RIGHT default: return fmt.Errorf("Invalid direction: %s", bs) } return nil }
// Scan implements the Scanner interface. func (d *Dimension) Scan(state fmt.ScanState, verb rune) error { var v Dimension if verb != 'v' { return fmt.Errorf("Dimension.Scan: invalid verb %c", verb) } // Scan number. tok, err := state.Token(true, numberToken) if err != nil { return err } value := string(tok) if value == "" { return fmt.Errorf("number is required") } if err := v.Value.Set(value); err != nil { return fmt.Errorf("%q is not a valid dimension: %v", value, err) } // Scan unit. The unit follows immediately after the number. tok, err = state.Token(false, unitToken) if err != nil { return err } unit := string(tok) if err := v.Unit.Set(unit); err != nil { return fmt.Errorf("\"%s%s\" is not a valid dimension: %v", value, unit, err) } if v.Unit == NoUnit && v.Value != 0 { return fmt.Errorf("%q is not a valid dimension: unit is required", value) } *d = v return nil }
func (s *Suit) Scan(st fmt.ScanState, x int) os.Error { str, e := st.Token() *s = ReadSuit(str) return e }
func (sum *SpamSum) Scan(state fmt.ScanState, verb rune) error { var blocksize int var leftPart, rightPart, blockPart, buffer []byte var err error if blockPart, err = state.Token(false, // do not skip spaces func(r rune) bool { return unicode.IsDigit(r) }); err != nil { return err } else if len(blockPart) == 0 { return errors.New("Cannot read block size.") } if blocksize, err = strconv.Atoi(string(blockPart)); err != nil { return err } else if blocksize < 3 { return errors.New("Block size too small") } if r, _, err := state.ReadRune(); err != nil { return err } else if r != ':' { return errors.New("Invalid token delimiter") } if buffer, err = state.Token(false, // do not skip spaces func(r rune) bool { return (bytes.IndexRune([]byte(b64), r) != -1) }); err != nil { return err } else if len(buffer) > SpamsumLength { return errors.New("First base64 string too long") } leftPart = make([]byte, len(buffer)) copy(leftPart, buffer[:]) if r, _, err := state.ReadRune(); err != nil { return err } else if r != ':' { return errors.New("Invalid token delimiter") } if buffer, err = state.Token(false, // do not skip spaces func(r rune) bool { return (bytes.IndexRune([]byte(b64), r) != -1) }); err != nil { return err } else if len(buffer) > (SpamsumLength / 2) { return errors.New("Second base64 string too long") } rightPart = make([]byte, len(buffer)) copy(rightPart[:], buffer) sum.blocksize = uint32(blocksize) copy(sum.leftPart[:], leftPart) copy(sum.rightPart[:], rightPart) sum.leftIndex = len(leftPart) sum.rightIndex = len(rightPart) return nil }
func (node *Node) Scan(state fmt.ScanState, verb int) os.Error { nameBytes, err := state.Token(true, nil) if err != nil { return err } if len(nameBytes) == 0 { return os.EOF } nameBytes = dup(nameBytes) extIPBytes, err := state.Token(true, nil) if err != nil { return err } extIPBytes = dup(extIPBytes) intIP4Bytes, err := state.Token(true, nil) if err != nil { return err } intIP4Bytes = dup(intIP4Bytes) intIP6Bytes, err := state.Token(true, nil) if err != nil { return err } intIP6Bytes = dup(intIP6Bytes) name := string(nameBytes) if len(name) < 1 { return NameTooShort } if len(name) > maxNameLen { return NameTooLong } extIP := net.ParseIP(string(extIPBytes)) if extIP == nil { return ExtIPInvalid } intIP4 := net.ParseIP(string(intIP4Bytes)) if intIP4 == nil { return IntIP4Invalid } intIP4 = intIP4.To4() if intIP4 == nil { return IntIP6Invalid } intIP6 := net.ParseIP(string(intIP6Bytes)) if intIP6 == nil { return IntIP6Invalid } if intIP6.To4() != nil { return IntIP6Invalid } node.Name = name node.ExtIP = extIP node.IntIP4 = intIP4 node.IntIP6 = intIP6 return nil }
// Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts formats whose verbs are supported by // fmt.Scan for floating point values, which are: // 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'. // Scan doesn't handle ±Inf. func (z *Float) Scan(s fmt.ScanState, ch rune) error { s.SkipSpace() _, _, err := z.scan(byteReader{s}, 0) return err }
// Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts the formats 'b' (binary), 'o' (octal), // 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). func (z *Int) Scan(s fmt.ScanState, ch rune) error { s.SkipSpace() // skip leading space characters base := 0 switch ch { case 'b': base = 2 case 'o': base = 8 case 'd': base = 10 case 'x', 'X': base = 16 case 's', 'v': // let scan determine the base case 'z': base = 60 default: return errors.New("Int.Scan: invalid verb") } charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz." if base != 0 { charset = charset[:base] } // Read the number into in in := make([]byte, 0, 16) var err error var n int for { ch, n, err = s.ReadRune() if err == io.EOF { break } if err != nil { return err } if n > 1 { // Wide character - must be the end s.UnreadRune() break } if len(in) == 0 { if ch == '+' { // Skip leading + as gmp doesn't understand them continue } if ch == '-' { goto ok } } if len(in) == 1 && base == 0 { if ch == 'b' || ch == 'x' { goto ok } } if !strings.ContainsRune(charset, ch) { // Bad character - end s.UnreadRune() break } ok: in = append(in, byte(ch)) } // Use GMP to convert it as it is very efficient for large numbers z.doinit() // null terminate for C in = append(in, 0) if C.mpz_set_str(&z.i[0], (*C.char)(unsafe.Pointer(&in[0])), C.int(base)) < 0 { return errors.New("Int.Scan: failed") } return nil }