summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-ffmpreg/util/funcs.go
blob: 4b584cf41198bbe68358e88c1f8d61e7c852aa21 (plain)
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
package util

import (
	"context"
	"os"
	"path"
	"strconv"
	"time"

	"github.com/tetratelabs/wazero/api"
)

// Wasm_Tempnam wraps Go_Tempnam to fulfill wazero's api.GoModuleFunc,
// the argument definition is (i32, i32) and return definition is (i32).
// NOTE: the calling module MUST have access to exported malloc / free.
func Wasm_Tempnam(ctx context.Context, mod api.Module, stack []uint64) {
	dirptr := api.DecodeU32(stack[0])
	pfxptr := api.DecodeU32(stack[1])
	dir := readString(ctx, mod, dirptr, 0)
	pfx := readString(ctx, mod, pfxptr, 0)
	tmpstr := Go_Tempnam(dir, pfx)
	tmpptr := writeString(ctx, mod, tmpstr)
	stack[0] = api.EncodeU32(tmpptr)
}

// Go_Tempname is functionally similar to C's tempnam.
func Go_Tempnam(dir, prefix string) string {
	now := time.Now().Unix()
	prefix = path.Join(dir, prefix)
	for i := 0; i < 1000; i++ {
		n := murmur2(uint32(now + int64(i)))
		name := prefix + strconv.FormatUint(uint64(n), 10)
		_, err := os.Stat(name)
		if err == nil {
			continue
		} else if os.IsNotExist(err) {
			return name
		} else {
			panic(err)
		}
	}
	panic("too many attempts")
}

// murmur2 is a simple uint32 murmur2 hash
// impl with fixed seed and input size.
func murmur2(k uint32) (h uint32) {
	const (
		//  seed ^ bitlen
		s = uint32(2147483647) ^ 8

		M = 0x5bd1e995
		R = 24
	)
	h = s
	k *= M
	k ^= k >> R
	k *= M
	h *= M
	h ^= k
	h ^= h >> 13
	h *= M
	h ^= h >> 15
	return
}