// indexRegexp returns the index of the first string from current scanning position that matches given regular expression // // It returns -1 if not found func (l *Lexer) indexRegexp(r *regexp.Regexp) int { loc := r.FindStringIndex(l.input[l.pos:]) if loc == nil { return -1 } return loc[0] }
func (b *Buffer) ConsumeRegexp(r *regexp.Regexp) bool { index := r.FindStringIndex(b.input[b.pos:]) if index == nil { return false } b.pos += (index[1] - index[0]) return true }
// matchRegexp checks if a value is a string and matches a specified regexp. func matchRegexp(exp interface{}, str interface{}) bool { var r *regexp.Regexp if rr, ok := exp.(*regexp.Regexp); ok { r = rr } else { r = regexp.MustCompile(fmt.Sprint(exp)) } return (r.FindStringIndex(fmt.Sprint(str)) != nil) }
func CertMatchesRegex(r *regexp.Regexp, cert *x509.Certificate) bool { if r.FindStringIndex(cert.Subject.CommonName) != nil { return true } for _, alt := range cert.DNSNames { if r.FindStringIndex(alt) != nil { return true } } return false }
func replaceFirst(re *regexp.Regexp, s string, replacement string) string { // Note that ReplaceAllStringFunc cannot be used here since it does // not replace $1 placeholders. loc := re.FindStringIndex(s) if nil == loc { return s } firstMatch := s[loc[0]:loc[1]] firstMatchReplaced := re.ReplaceAllString(firstMatch, replacement) return s[0:loc[0]] + firstMatchReplaced + s[loc[1]:] }
func regexpFindIndex( needle regexp.Regexp, haystack string) (Sexp, error) { loc := needle.FindStringIndex(haystack) arr := make([]Sexp, len(loc)) for i := range arr { arr[i] = Sexp(SexpInt(loc[i])) } return SexpArray(arr), nil }
func regexpFindIndex( needle *regexp.Regexp, haystack string) (Sexp, error) { loc := needle.FindStringIndex(haystack) arr := make([]Sexp, len(loc)) for i := range arr { arr[i] = Sexp(&SexpInt{Val: int64(loc[i])}) } return &SexpArray{Val: arr}, nil }
func SplitPathWithSeparatorRegex(r *regexp.Regexp, path string) (head, tail, sep string) { indices := r.FindStringIndex(path) if indices != nil { head = path[:indices[0]] tail = path[indices[1]:] sep = path[indices[0]:indices[1]] } else { head = path tail = "" sep = "" } return }
func (w *Web) pathDealer(re *regexp.Regexp, str fmt.Stringer) { names := re.SubexpNames() matches := re.FindStringSubmatch(str.String()) for key, name := range names { if name != "" { w.Param.Set(name, matches[key]) } } switch str.(type) { case pathStr: w.pri.curpath += matches[0] w.pri.path = w.pri.path[re.FindStringIndex(w.pri.path)[1]:] } }
// Given a string starting with a token, find the end of the token (the index of the first character that follows the token). // Rules: // * If the token starts with a double quote ("), the token ends at the next double quote that isn't backslash-escaped. // * Otherwise the token ends right before the next syntax character. // Returns a negative value if there is no valid token. func findTokenEnd(s string) int { var re *regexp.Regexp switch s[0] { case '"': re = stringRegex case '\'': re = charRegex default: re = tokenRegex } loc := re.FindStringIndex(s) if loc == nil { return -1 } else { return loc[1] // ending index of regex match } }
func split(s string, r *regexp.Regexp) (bool, string, string) { index := r.FindStringIndex(s) if index == nil { return false, "", "" } if index[0] == 0 { index[0] = index[1] } first := strings.TrimSpace(s[:index[0]]) rest := strings.TrimSpace(s[index[0]:]) if len(first) > 0 { return true, first, rest } else { return split(rest, r) } }
// RegExp 正規表現を使用するパーサーを返す func RegExp(pattern *regexp.Regexp) Parser { return func(target string, position int) *Result { if position > len(target) { return incompatible(position) } sample := target[position:] if pattern.MatchString(sample) { index := pattern.FindStringIndex(sample) return &Result{ Success: true, Target: pattern.FindString(sample), Position: position + index[1], Attributes: map[string]string{}, } } return incompatible(position) } }
func StrMatch(s string, re *regexp.Regexp) bool { return nil != re.FindStringIndex(s) }
// Generate is given a list of *.go files to parse, and an output file (fout). // // It finds all types T in the files, and it creates 2 tmp files (frun). // - main package file passed to 'go run' // - package level file which calls *genRunner.Selfer to write Selfer impls for each T. // We use a package level file so that it can reference unexported types in the package being worked on. // Tool then executes: "go run __frun__" which creates fout. // fout contains Codec(En|De)codeSelf implementations for every type T. // func Generate(outfile, buildTag, codecPkgPath string, uid int64, useUnsafe bool, goRunTag string, st string, regexName *regexp.Regexp, notRegexName *regexp.Regexp, deleteTempFile bool, infiles ...string) (err error) { // For each file, grab AST, find each type, and write a call to it. if len(infiles) == 0 { return } if outfile == "" || codecPkgPath == "" { err = errors.New("outfile and codec package path cannot be blank") return } if uid < 0 { uid = -uid } if uid == 0 { rr := rand.New(rand.NewSource(time.Now().UnixNano())) uid = 101 + rr.Int63n(9777) } // We have to parse dir for package, before opening the temp file for writing (else ImportDir fails). // Also, ImportDir(...) must take an absolute path. lastdir := filepath.Dir(outfile) absdir, err := filepath.Abs(lastdir) if err != nil { return } pkg, err := build.Default.ImportDir(absdir, build.AllowBinary) if err != nil { return } type tmplT struct { CodecPkgName string CodecImportPath string ImportPath string OutFile string PackageName string RandString string BuildTag string StructTags string Types []string CodecPkgFiles bool UseUnsafe bool } tv := tmplT{ CodecPkgName: genCodecPkg, OutFile: outfile, CodecImportPath: codecPkgPath, BuildTag: buildTag, UseUnsafe: useUnsafe, RandString: strconv.FormatInt(uid, 10), StructTags: st, } tv.ImportPath = pkg.ImportPath if tv.ImportPath == tv.CodecImportPath { tv.CodecPkgFiles = true tv.CodecPkgName = "codec" } else { // HACK: always handle vendoring. It should be typically on in go 1.6, 1.7 s := tv.ImportPath const vendorStart = "vendor/" const vendorInline = "/vendor/" if i := strings.LastIndex(s, vendorInline); i >= 0 { tv.ImportPath = s[i+len(vendorInline):] } else if strings.HasPrefix(s, vendorStart) { tv.ImportPath = s[len(vendorStart):] } } astfiles := make([]*ast.File, len(infiles)) for i, infile := range infiles { if filepath.Dir(infile) != lastdir { err = errors.New("in files must all be in same directory as outfile") return } fset := token.NewFileSet() astfiles[i], err = parser.ParseFile(fset, infile, nil, 0) if err != nil { return } if i == 0 { tv.PackageName = astfiles[i].Name.Name if tv.PackageName == "main" { // codecgen cannot be run on types in the 'main' package. // A temporary 'main' package must be created, and should reference the fully built // package containing the types. // Also, the temporary main package will conflict with the main package which already has a main method. err = errors.New("codecgen cannot be run on types in the 'main' package") return } } } for _, f := range astfiles { for _, d := range f.Decls { if gd, ok := d.(*ast.GenDecl); ok { for _, dd := range gd.Specs { if td, ok := dd.(*ast.TypeSpec); ok { // if len(td.Name.Name) == 0 || td.Name.Name[0] > 'Z' || td.Name.Name[0] < 'A' { if len(td.Name.Name) == 0 { continue } // only generate for: // struct: StructType // primitives (numbers, bool, string): Ident // map: MapType // slice, array: ArrayType // chan: ChanType // do not generate: // FuncType, InterfaceType, StarExpr (ptr), etc switch td.Type.(type) { case *ast.StructType, *ast.Ident, *ast.MapType, *ast.ArrayType, *ast.ChanType: if regexName.FindStringIndex(td.Name.Name) != nil && notRegexName.FindStringIndex(td.Name.Name) == nil { tv.Types = append(tv.Types, td.Name.Name) } } } } } } } if len(tv.Types) == 0 { return } // we cannot use ioutil.TempFile, because we cannot guarantee the file suffix (.go). // Also, we cannot create file in temp directory, // because go run will not work (as it needs to see the types here). // Consequently, create the temp file in the current directory, and remove when done. // frun, err = ioutil.TempFile("", "codecgen-") // frunName := filepath.Join(os.TempDir(), "codecgen-"+strconv.FormatInt(time.Now().UnixNano(), 10)+".go") frunMainName := "codecgen-main-" + tv.RandString + ".generated.go" frunPkgName := "codecgen-pkg-" + tv.RandString + ".generated.go" if deleteTempFile { defer os.Remove(frunMainName) defer os.Remove(frunPkgName) } // var frunMain, frunPkg *os.File if _, err = gen1(frunMainName, genFrunMainTmpl, &tv); err != nil { return } if _, err = gen1(frunPkgName, genFrunPkgTmpl, &tv); err != nil { return } // remove outfile, so "go run ..." will not think that types in outfile already exist. os.Remove(outfile) // execute go run frun cmd := exec.Command("go", "run", "-tags="+goRunTag, frunMainName) //, frunPkg.Name()) var buf bytes.Buffer cmd.Stdout = &buf cmd.Stderr = &buf if err = cmd.Run(); err != nil { err = fmt.Errorf("error running 'go run %s': %v, console: %s", frunMainName, err, buf.Bytes()) return } os.Stdout.Write(buf.Bytes()) return }