gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

line.go (3033B)


      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package objabi
      6 
      7 import (
      8 	"os"
      9 	"path/filepath"
     10 	"strings"
     11 )
     12 
     13 // WorkingDir returns the current working directory
     14 // (or "/???" if the directory cannot be identified),
     15 // with "/" as separator.
     16 func WorkingDir() string {
     17 	var path string
     18 	path, _ = os.Getwd()
     19 	if path == "" {
     20 		path = "/???"
     21 	}
     22 	return filepath.ToSlash(path)
     23 }
     24 
     25 // AbsFile returns the absolute filename for file in the given directory,
     26 // as rewritten by the rewrites argument.
     27 // For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT".
     28 // If the resulting path is the empty string, the result is "??".
     29 //
     30 // The rewrites argument is a ;-separated list of rewrites.
     31 // Each rewrite is of the form "prefix" or "prefix=>replace",
     32 // where prefix must match a leading sequence of path elements
     33 // and is either removed entirely or replaced by the replacement.
     34 func AbsFile(dir, file, rewrites string) string {
     35 	abs := file
     36 	if dir != "" && !filepath.IsAbs(file) {
     37 		abs = filepath.Join(dir, file)
     38 	}
     39 
     40 	start := 0
     41 	for i := 0; i <= len(rewrites); i++ {
     42 		if i == len(rewrites) || rewrites[i] == ';' {
     43 			if new, ok := applyRewrite(abs, rewrites[start:i]); ok {
     44 				abs = new
     45 				goto Rewritten
     46 			}
     47 			start = i + 1
     48 		}
     49 	}
     50 	if hasPathPrefix(abs, GOROOT) {
     51 		abs = "$GOROOT" + abs[len(GOROOT):]
     52 	}
     53 
     54 Rewritten:
     55 	if abs == "" {
     56 		abs = "??"
     57 	}
     58 	return abs
     59 }
     60 
     61 // applyRewrite applies the rewrite to the path,
     62 // returning the rewritten path and a boolean
     63 // indicating whether the rewrite applied at all.
     64 func applyRewrite(path, rewrite string) (string, bool) {
     65 	prefix, replace := rewrite, ""
     66 	if j := strings.LastIndex(rewrite, "=>"); j >= 0 {
     67 		prefix, replace = rewrite[:j], rewrite[j+len("=>"):]
     68 	}
     69 
     70 	if prefix == "" || !hasPathPrefix(path, prefix) {
     71 		return path, false
     72 	}
     73 	if len(path) == len(prefix) {
     74 		return replace, true
     75 	}
     76 	if replace == "" {
     77 		return path[len(prefix)+1:], true
     78 	}
     79 	return replace + path[len(prefix):], true
     80 }
     81 
     82 // Does s have t as a path prefix?
     83 // That is, does s == t or does s begin with t followed by a slash?
     84 // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
     85 // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true.
     86 // We do not allow full Unicode case folding, for fear of causing more confusion
     87 // or harm than good. (For an example of the kinds of things that can go wrong,
     88 // see http://article.gmane.org/gmane.linux.kernel/1853266.)
     89 func hasPathPrefix(s string, t string) bool {
     90 	if len(t) > len(s) {
     91 		return false
     92 	}
     93 	var i int
     94 	for i = 0; i < len(t); i++ {
     95 		cs := int(s[i])
     96 		ct := int(t[i])
     97 		if 'A' <= cs && cs <= 'Z' {
     98 			cs += 'a' - 'A'
     99 		}
    100 		if 'A' <= ct && ct <= 'Z' {
    101 			ct += 'a' - 'A'
    102 		}
    103 		if cs == '\\' {
    104 			cs = '/'
    105 		}
    106 		if ct == '\\' {
    107 			ct = '/'
    108 		}
    109 		if cs != ct {
    110 			return false
    111 		}
    112 	}
    113 	return i >= len(s) || s[i] == '/' || s[i] == '\\'
    114 }