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 15package android 16 17import ( 18 "runtime" 19 "sort" 20 "strings" 21) 22 23func 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 48func 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 57func 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 67func inList(s string, list []string) bool { 68 return indexList(s, list) != -1 69} 70 71// checkCalledFromInit panics if a Go package's init function is not on the 72// call stack. 73func checkCalledFromInit() { 74 for skip := 3; ; skip++ { 75 _, funcName, ok := callerName(skip) 76 if !ok { 77 panic("not called from an init func") 78 } 79 80 if funcName == "init" || strings.HasPrefix(funcName, "init·") { 81 return 82 } 83 } 84} 85 86// callerName returns the package path and function name of the calling 87// function. The skip argument has the same meaning as the skip argument of 88// runtime.Callers. 89func callerName(skip int) (pkgPath, funcName string, ok bool) { 90 var pc [1]uintptr 91 n := runtime.Callers(skip+1, pc[:]) 92 if n != 1 { 93 return "", "", false 94 } 95 96 f := runtime.FuncForPC(pc[0]) 97 fullName := f.Name() 98 99 lastDotIndex := strings.LastIndex(fullName, ".") 100 if lastDotIndex == -1 { 101 panic("unable to distinguish function name from package") 102 } 103 104 if fullName[lastDotIndex-1] == ')' { 105 // The caller is a method on some type, so it's name looks like 106 // "pkg/path.(type).method". We need to go back one dot farther to get 107 // to the package name. 108 lastDotIndex = strings.LastIndex(fullName[:lastDotIndex], ".") 109 } 110 111 pkgPath = fullName[:lastDotIndex] 112 funcName = fullName[lastDotIndex+1:] 113 ok = true 114 return 115} 116