Home | History | Annotate | Download | only in android
      1 // Copyright 2015 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package android
     16 
     17 import (
     18 	"runtime"
     19 	"sort"
     20 	"strings"
     21 )
     22 
     23 func JoinWithPrefix(strs []string, prefix string) string {
     24 	if len(strs) == 0 {
     25 		return ""
     26 	}
     27 
     28 	if len(strs) == 1 {
     29 		return prefix + strs[0]
     30 	}
     31 
     32 	n := len(" ") * (len(strs) - 1)
     33 	for _, s := range strs {
     34 		n += len(prefix) + len(s)
     35 	}
     36 
     37 	ret := make([]byte, 0, n)
     38 	for i, s := range strs {
     39 		if i != 0 {
     40 			ret = append(ret, ' ')
     41 		}
     42 		ret = append(ret, prefix...)
     43 		ret = append(ret, s...)
     44 	}
     45 	return string(ret)
     46 }
     47 
     48 func sortedKeys(m map[string][]string) []string {
     49 	s := make([]string, 0, len(m))
     50 	for k := range m {
     51 		s = append(s, k)
     52 	}
     53 	sort.Strings(s)
     54 	return s
     55 }
     56 
     57 func indexList(s string, list []string) int {
     58 	for i, l := range list {
     59 		if l == s {
     60 			return i
     61 		}
     62 	}
     63 
     64 	return -1
     65 }
     66 
     67 func inList(s string, list []string) bool {
     68 	return indexList(s, list) != -1
     69 }
     70 
     71 func prefixInList(s string, list []string) bool {
     72 	for _, prefix := range list {
     73 		if strings.HasPrefix(s, prefix) {
     74 			return true
     75 		}
     76 	}
     77 	return false
     78 }
     79 
     80 // checkCalledFromInit panics if a Go package's init function is not on the
     81 // call stack.
     82 func checkCalledFromInit() {
     83 	for skip := 3; ; skip++ {
     84 		_, funcName, ok := callerName(skip)
     85 		if !ok {
     86 			panic("not called from an init func")
     87 		}
     88 
     89 		if funcName == "init" || strings.HasPrefix(funcName, "init") {
     90 			return
     91 		}
     92 	}
     93 }
     94 
     95 // callerName returns the package path and function name of the calling
     96 // function.  The skip argument has the same meaning as the skip argument of
     97 // runtime.Callers.
     98 func callerName(skip int) (pkgPath, funcName string, ok bool) {
     99 	var pc [1]uintptr
    100 	n := runtime.Callers(skip+1, pc[:])
    101 	if n != 1 {
    102 		return "", "", false
    103 	}
    104 
    105 	f := runtime.FuncForPC(pc[0])
    106 	fullName := f.Name()
    107 
    108 	lastDotIndex := strings.LastIndex(fullName, ".")
    109 	if lastDotIndex == -1 {
    110 		panic("unable to distinguish function name from package")
    111 	}
    112 
    113 	if fullName[lastDotIndex-1] == ')' {
    114 		// The caller is a method on some type, so it's name looks like
    115 		// "pkg/path.(type).method".  We need to go back one dot farther to get
    116 		// to the package name.
    117 		lastDotIndex = strings.LastIndex(fullName[:lastDotIndex], ".")
    118 	}
    119 
    120 	pkgPath = fullName[:lastDotIndex]
    121 	funcName = fullName[lastDotIndex+1:]
    122 	ok = true
    123 	return
    124 }
    125