package gogeouri import ( "errors" "strconv" "strings" ) type Geo struct { Latitude, Longitude, Altitude float64 Parameters map[string][]string } const scheme = "geo" func Parse(uri string) (*Geo, error) { g := &Geo{ Parameters: map[string][]string{}, } if !strings.HasPrefix(uri, scheme+":") { return nil, errors.New("no or wrong scheme") } uri = strings.TrimPrefix(uri, scheme+":") uriParts := strings.Split(uri, ";") if len(strings.TrimSpace(uriParts[0])) < 1 { return nil, errors.New("empty path") } coords := strings.Split(uriParts[0], ",") if l := len(coords); l < 2 || l > 3 { return nil, errors.New("wrong number of coordinates") } if f, e := strconv.ParseFloat(coords[0], 64); e == nil { g.Latitude = f } else { return nil, errors.New("can't parse latitude") } if f, e := strconv.ParseFloat(coords[1], 64); e == nil { g.Longitude = f } else { return nil, errors.New("can't parse longitude") } if len(coords) == 3 { if f, e := strconv.ParseFloat(coords[2], 64); e == nil { g.Altitude = f } else { return nil, errors.New("can't parse altitude") } } for _, p := range uriParts[1:] { pParts := strings.Split(p, "=") if l := len(pParts); l == 1 { if _, ok := g.Parameters[pParts[0]]; !ok { g.Parameters[pParts[0]] = []string{} } } else if l == 2 { g.Parameters[pParts[0]] = append(g.Parameters[pParts[0]], pParts[1]) } else { return nil, errors.New("wrong parameter") } } return g, nil }