File: string.go

package info (click to toggle)
c2go 0.26.11-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,052 kB
  • sloc: ansic: 6,037; sh: 82; makefile: 5
file content (194 lines) | stat: -rw-r--r-- 6,026 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package noarch

import (
	"bytes"
	"strings"
	"unsafe"
)

// Strlen returns the length of a string.
//
// The length of a C string is determined by the terminating null-character: A
// C string is as long as the number of characters between the beginning of the
// string and the terminating null character (without including the terminating
// null character itself).
func Strlen(a *byte) int32 {
	// TODO: The transpiler should have a syntax that means this proxy function
	// does not need to exist.

	return int32(len(CStringToString(a)))
}

// Strcpy copies the C string pointed by source into the array pointed by
// destination, including the terminating null character (and stopping at that
// point).
//
// To avoid overflows, the size of the array pointed by destination shall be
// long enough to contain the same C string as source (including the terminating
// null character), and should not overlap in memory with source.
func Strcpy(dest, src *byte) *byte {
	var (
		pSrc  *byte
		pDest *byte
		i     int
	)
	for ; ; i++ {
		pSrc = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + uintptr(i)))
		pDest = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dest)) + uintptr(i)))
		*pDest = *pSrc

		// We only need to copy until the first NULL byte. Make sure we also
		// include that NULL byte on the end.
		if *pSrc == '\x00' {
			break
		}
	}

	return dest
}

// Strncpy copies the first num characters of source to destination. If the end
// of the source C string (which is signaled by a null-character) is found
// before num characters have been copied, destination is padded with zeros
// until a total of num characters have been written to it.
//
// No null-character is implicitly appended at the end of destination if source
// is longer than num. Thus, in this case, destination shall not be considered a
// null terminated C string (reading it as such would overflow).
//
// destination and source shall not overlap (see memmove for a safer alternative
// when overlapping).
func Strncpy(dest, src *byte, len int32) *byte {
	// Copy up to the len or first NULL bytes - whichever comes first.
	var (
		pSrc  = src
		pDest = dest
		i     int32
	)
	for i < len && *pSrc != 0 {
		*pDest = *pSrc
		i++
		pSrc = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + uintptr(i)))
		pDest = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dest)) + uintptr(i)))
	}

	// The rest of the dest will be padded with zeros to the len.
	for i < len {
		*pDest = 0
		i++
		pDest = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dest)) + uintptr(i)))
	}

	return dest
}

// Strcasestr - function is similar to Strstr(),
// but ignores the case of both strings.
func Strcasestr(str1, str2 *byte) *byte {
	a := strings.ToLower(CStringToString(str1))
	b := strings.ToLower(CStringToString(str2))
	index := strings.Index(a, b)
	if index == -1 {
		return nil
	}
	return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(str1)) + uintptr(index)))
}

// Strcat - concatenate strings
// Appends a copy of the source string to the destination string.
// The terminating null character in destination is overwritten by the first
// character of source, and a null-character is included at the end
// of the new string formed by the concatenation of both in destination.
func Strcat(dest, src *byte) *byte {
	newDest := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dest)) + uintptr(Strlen(dest))))
	Strcpy(newDest, src)
	return dest
}

// Strcmp - compare two strings
// Compares the C string str1 to the C string str2.
func Strcmp(str1, str2 *byte) int32 {
	return int32(bytes.Compare([]byte(CStringToString(str1)), []byte(CStringToString(str2))))
}

// Strncmp - compare two strings
// Compares the C string str1 to the C string str2 upto the first NULL character
// or n-th character whichever comes first.
func Strncmp(str1, str2 *byte, n int32) int32 {
	a := []byte(CStringToString(str1))
	a = a[:int(min(int(n), len(a)))]
	b := []byte(CStringToString(str2))
	b = b[:int(min(int(n), len(b)))]
	return int32(bytes.Compare(a, b))
}

// Strstr - locate a substring in a string
// function locates the first occurrence of the null-terminated string needle
// in the null-terminated string haystack.
func Strstr(str1, str2 *byte) *byte {
	a := CStringToString(str1)
	b := CStringToString(str2)
	index := strings.Index(a, b)
	if index == -1 {
		return nil
	}
	return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(str1)) + uintptr(index)))
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// Strchr - Locate first occurrence of character in string
// See: http://www.cplusplus.com/reference/cstring/strchr/
func Strchr(str *byte, ch int32) *byte {
	i := 0
	var pStr = str
	for {
		if *pStr == '\x00' {
			break
		}
		if int32(*pStr) == ch {
			return pStr
		}
		i++
		pStr = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(str)) + uintptr(i)))
	}
	return nil
}

// Memset treats dst as a binary array and sets size bytes to the value val.
// Returns dst.
func Memset(dst unsafe.Pointer, val int32, size int32) unsafe.Pointer {
	data := toByteSlice((*byte)(dst), size)
	var i int32
	var vb = byte(val)
	for i = 0; i < size; i++ {
		data[i] = vb
	}
	return dst
}

// Memcpy treats dst and src as binary arrays and copies size bytes from src to dst.
// Returns dst.
// While in C it it is undefined behavior to call memcpy with overlapping regions,
// in Go we rely on the built-in copy function, which has no such limitation.
// To copy overlapping regions in C memmove should be used, so we map that function
// to Memcpy as well.
func Memcpy(dst unsafe.Pointer, src unsafe.Pointer, size int32) unsafe.Pointer {
	bDst := toByteSlice((*byte)(dst), size)
	bSrc := toByteSlice((*byte)(src), size)
	copy(bDst, bSrc)
	return dst
}

// Memcmp compares two binary arrays upto n bytes.
// Different from strncmp, memcmp does not stop at the first NULL byte.
func Memcmp(src1, src2 unsafe.Pointer, n int32) int32 {
	b1 := toByteSlice((*byte)(src1), n)
	b2 := toByteSlice((*byte)(src2), n)
	return int32(bytes.Compare(b1, b2))
}