github.com/jwijenbergh/purego@v0.0.0-20240126093400-70ff3a61df13/internal/strings/strings.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
     3  
     4  package strings
     5  
     6  import (
     7  	"unsafe"
     8  )
     9  
    10  // hasSuffix tests whether the string s ends with suffix.
    11  func hasSuffix(s, suffix string) bool {
    12  	return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
    13  }
    14  
    15  func ByteSlice(name []string) **byte {
    16  	if name == nil {
    17  		return nil
    18  	}
    19  	res := make([]*byte, len(name)+1)
    20  	for i, v := range name {
    21  		res[i] = CString(v)
    22  	}
    23  	res[len(name)] = nil
    24  	return &res[0]
    25  }
    26  
    27  // CString converts a go string to *byte that can be passed to C code.
    28  func CString(name string) *byte {
    29  	if hasSuffix(name, "\x00") {
    30  		return &(*(*[]byte)(unsafe.Pointer(&name)))[0]
    31  	}
    32  	b := make([]byte, len(name)+1)
    33  	copy(b, name)
    34  	return &b[0]
    35  }
    36  
    37  // GoString copies a null-terminated char* to a Go string.
    38  func GoString(c uintptr) string {
    39  	// We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer
    40  	ptr := *(*unsafe.Pointer)(unsafe.Pointer(&c))
    41  	if ptr == nil {
    42  		return ""
    43  	}
    44  	var length int
    45  	for {
    46  		if *(*byte)(unsafe.Add(ptr, uintptr(length))) == '\x00' {
    47  			break
    48  		}
    49  		length++
    50  	}
    51  	return string(unsafe.Slice((*byte)(ptr), length))
    52  }