github.com/gotranspile/cxgo@v0.3.7/runtime/libc/wstring.go (about)

     1  package libc
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  	"unicode/utf8"
     7  	"unsafe"
     8  )
     9  
    10  const WCharSize = int(unsafe.Sizeof(WChar(0)))
    11  
    12  // IndexWCharPtr unsafely moves a wide char pointer by i elements. An offset may be negative.
    13  //
    14  // Deprecated: use unsafe.Add
    15  func IndexWCharPtr(p *WChar, i int) *WChar {
    16  	return (*WChar)(unsafe.Add(unsafe.Pointer(p), i*WCharSize))
    17  }
    18  
    19  // UnsafeWCharN makes a slice of a given size starting at ptr.
    20  //
    21  // Deprecated: use unsafe.Slice
    22  func UnsafeWCharN(ptr unsafe.Pointer, sz uint64) []WChar {
    23  	return unsafe.Slice((*WChar)(ptr), sz)
    24  }
    25  
    26  // WCharN makes a slice of a given size starting at ptr.
    27  // It accepts a *WChar instead of unsafe pointer as UnsafeWCharN does, which allows to avoid unsafe import.
    28  //
    29  // Deprecated: use unsafe.Slice
    30  func WCharN(p *WChar, sz uint64) []WChar {
    31  	return unsafe.Slice(p, sz)
    32  }
    33  
    34  // CWString makes a new zero-terminated wide char array containing a given string.
    35  func CWString(s string) *WChar {
    36  	sz := utf8.RuneCountInString(s)
    37  	p := makePad((sz+2)*int(unsafe.Sizeof(WChar(0))), 0)
    38  
    39  	w := unsafe.Slice((*WChar)(unsafe.Pointer(&p[0])), uint64(sz))
    40  	w = w[:0]
    41  	for _, r := range s {
    42  		w = append(w, WChar(r))
    43  	}
    44  	if cap(w) != sz {
    45  		panic("must not happen")
    46  	}
    47  	return &w[0]
    48  }
    49  
    50  func WStrLen(str *WChar) uint64 {
    51  	return uint64(findnullw(str))
    52  }
    53  
    54  func GoWSlice(ptr *WChar) []WChar {
    55  	n := WStrLen(ptr)
    56  	if n == 0 {
    57  		return nil
    58  	}
    59  	return unsafe.Slice(ptr, n)
    60  }
    61  
    62  func GoWString(s *WChar) string {
    63  	return gostringw(s)
    64  }
    65  
    66  func WStrCpy(dst, src *WChar) *WChar {
    67  	s := GoWSlice(src)
    68  	d := unsafe.Slice(dst, len(s)+1)
    69  	n := copy(d, s)
    70  	d[n] = 0
    71  	return dst
    72  }
    73  
    74  func WStrNCpy(dst, src *WChar, sz uint32) *WChar {
    75  	d := unsafe.Slice(dst, sz)
    76  	s := GoWSlice(src)
    77  	pad := 0
    78  	if len(s) > int(sz) {
    79  		s = s[:sz]
    80  	} else if len(s) < int(sz) {
    81  		pad = int(sz) - len(s)
    82  	}
    83  	n := copy(d, s)
    84  	for i := 0; i < pad; i++ {
    85  		d[n+i] = 0
    86  	}
    87  	return dst
    88  }
    89  
    90  func WStrChr(str *WChar, ch int64) *WChar {
    91  	if ch < 0 || ch > 0xffff {
    92  		panic(ch)
    93  	}
    94  	if str == nil {
    95  		return nil
    96  	}
    97  	b := GoWSlice(str)
    98  	for i, c := range b {
    99  		if c == WChar(ch) {
   100  			return &b[i]
   101  		}
   102  	}
   103  	return nil
   104  }
   105  
   106  func WStrCat(dst, src *WChar) *WChar {
   107  	s := GoWSlice(src)
   108  	i := WStrLen(dst)
   109  	n := int(i) + len(s)
   110  	d := unsafe.Slice(dst, n+1)
   111  	copy(d[i:], s)
   112  	d[n] = 0
   113  	return &d[0]
   114  }
   115  
   116  func WStrCmp(a, b *WChar) int {
   117  	s1 := GoWString(a)
   118  	s2 := GoWString(b)
   119  	return strings.Compare(s1, s2)
   120  }
   121  
   122  func WStrCaseCmp(a, b *WChar) int {
   123  	s1 := strings.ToLower(GoWString(a))
   124  	s2 := strings.ToLower(GoWString(b))
   125  	return strings.Compare(s1, s2)
   126  }
   127  
   128  func WStrtol(s *WChar, end **WChar, base int) int {
   129  	if end != nil {
   130  		panic("TODO")
   131  	}
   132  	str := GoWString(s)
   133  	v, err := strconv.ParseInt(str, base, 32)
   134  	if err != nil {
   135  		return 0
   136  	}
   137  	return int(v)
   138  }
   139  
   140  func Mbstowcs(a1 *WChar, a2 *byte, a3 uint32) uint32 {
   141  	panic("TODO")
   142  }
   143  
   144  func wIndexAny(s, chars []WChar) int {
   145  	for i, c1 := range s {
   146  		for _, c2 := range chars {
   147  			if c1 == c2 {
   148  				return i
   149  			}
   150  		}
   151  	}
   152  	return -1
   153  }
   154  
   155  func wIndex(s []WChar, c WChar) int {
   156  	for i, c1 := range s {
   157  		if c1 == c {
   158  			return i
   159  		}
   160  	}
   161  	return -1
   162  }
   163  
   164  var wstrtok struct {
   165  	data []WChar
   166  	ind  int
   167  }
   168  
   169  func WStrTok(src, delim *WChar) *WChar {
   170  	if src != nil {
   171  		wstrtok.data = GoWSlice(src)
   172  		wstrtok.ind = 0
   173  	}
   174  	d := GoWSlice(delim)
   175  	for ; wstrtok.ind < len(wstrtok.data); wstrtok.ind++ {
   176  		if wIndex(d, wstrtok.data[wstrtok.ind]) < 0 {
   177  			// start of a new token
   178  			tok := wstrtok.data[wstrtok.ind:]
   179  			if i := wIndexAny(tok, d); i >= 0 {
   180  				tok[i] = 0
   181  				wstrtok.ind += i + 1
   182  			} else {
   183  				wstrtok.data = nil
   184  				wstrtok.ind = 0
   185  			}
   186  			return &tok[0]
   187  		}
   188  		// skip delimiters
   189  	}
   190  	wstrtok.data = nil
   191  	wstrtok.ind = 0
   192  	return nil
   193  }