github.com/gramework/runtimer@v0.0.0-20211014201118-d25b6e2ccefd/string.go (about) 1 // Copyright 2014 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 runtimer 6 7 import "unsafe" // #nosec 8 9 type StringStruct struct { 10 Str unsafe.Pointer 11 Len int 12 } 13 14 // Variant with *byte pointer type for DWARF debugging. 15 type StringStructDWARF struct { 16 Str *byte 17 Len int 18 } 19 20 func StringStructOf(sp *string) *StringStruct { 21 return (*StringStruct)(unsafe.Pointer(sp)) 22 } 23 24 func Contains(s, t string) bool { 25 return Index(s, t) >= 0 26 } 27 28 func Index(s, t string) int { 29 if len(t) == 0 { 30 return 0 31 } 32 for i := 0; i < len(s); i++ { 33 if s[i] == t[0] && HasPrefix(s[i:], t) { 34 return i 35 } 36 } 37 return -1 38 } 39 40 func HasPrefix(s, t string) bool { 41 return len(s) >= len(t) && s[:len(t)] == t 42 } 43 44 const ( 45 maxUint = ^uint(0) 46 maxInt = int(maxUint >> 1) 47 ) 48 49 // Atoi parses an int from a string s. 50 // The bool result reports whether s is a number 51 // representable by a value of type int. 52 func Atoi(s string) (int, bool) { 53 if s == "" { 54 return 0, false 55 } 56 57 neg := false 58 if s[0] == '-' { 59 neg = true 60 s = s[1:] 61 } 62 63 un := uint(0) 64 for i := 0; i < len(s); i++ { 65 c := s[i] 66 if c < '0' || c > '9' { 67 return 0, false 68 } 69 if un > maxUint/10 { 70 // overflow 71 return 0, false 72 } 73 un *= 10 74 un1 := un + uint(c) - '0' 75 if un1 < un { 76 // overflow 77 return 0, false 78 } 79 un = un1 80 } 81 82 if !neg && un > uint(maxInt) { 83 return 0, false 84 } 85 if neg && un > uint(maxInt)+1 { 86 return 0, false 87 } 88 89 n := int(un) 90 if neg { 91 n = -n 92 } 93 94 return n, true 95 } 96 97 // Atoi32 is like Atoi but for integers 98 // that fit into an int32. 99 func Atoi32(s string) (int32, bool) { 100 if n, ok := Atoi(s); n == int(int32(n)) { 101 return int32(n), ok 102 } 103 return 0, false 104 } 105 106 func Findnull(s *byte) int { 107 return findnull(s) 108 } 109 110 //go:nosplit 111 //go:linkname findnull runtime.findnull 112 func findnull(s *byte) int 113 114 func Findnullw(s *uint16) int { 115 return findnullw(s) 116 } 117 118 //go:linkname findnullw runtime.findnullw 119 func findnullw(s *uint16) int 120 121 func Gostringnocopy(str *byte) string { 122 return gostringnocopy(str) 123 } 124 125 //go:nosplit 126 //go:linkname gostringnocopy runtime.gostringnocopy 127 func gostringnocopy(str *byte) string 128 129 const ( 130 PageShift uint = 13 131 132 // Public64bit = 1 on 64-bit systems, 0 on 32-bit systems 133 Public64bit uint = 1 << (^uintptr(0) >> 63) / 2 134 135 MHeapMapTotalBits = (Public64bit*GoosWindows)*35 + (Public64bit*(1-GoosWindows)*(1-GoosDarwin*GoarchArm64))*39 + GoosDarwin*GoarchArm64*31 + (1-Public64bit)*(32-(GoarchMips+GoarchMipsle)) 136 MHeapMapBits = MHeapMapTotalBits - PageShift 137 138 // MaxMem is the maximum heap arena size minus 1. 139 // 140 // On 32-bit, this is also the maximum heap pointer value, 141 // since the arena starts at address 0. 142 MaxMem = 1<<MHeapMapTotalBits - 1 143 ) 144 145 func gostringw(strw *uint16) string { 146 var buf [8]byte 147 str := (*[MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw)) 148 n1 := 0 149 for i := 0; str[i] != 0; i++ { 150 n1 += Encoderune(buf[:], rune(str[i])) 151 } 152 s, b := Rawstring(n1 + 4) 153 n2 := 0 154 for i := 0; str[i] != 0; i++ { 155 // check for race 156 if n2 >= n1 { 157 break 158 } 159 n2 += Encoderune(b[n2:], rune(str[i])) 160 } 161 b[n2] = 0 // for luck 162 return s[:n2] 163 }