summaryrefslogtreecommitdiffstats
path: root/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ParamPackage.kt
blob: 83fc7da3c054028e17ee4b5f9fb3a765677e2820 (plain) (blame)
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
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

package org.yuzu.yuzu_emu.utils

// Kotlin version of src/common/param_package.h
class ParamPackage(serialized: String = "") {
    private val KEY_VALUE_SEPARATOR = ":"
    private val PARAM_SEPARATOR = ","

    private val ESCAPE_CHARACTER = "$"
    private val KEY_VALUE_SEPARATOR_ESCAPE = "$0"
    private val PARAM_SEPARATOR_ESCAPE = "$1"
    private val ESCAPE_CHARACTER_ESCAPE = "$2"

    private val EMPTY_PLACEHOLDER = "[empty]"

    val data = mutableMapOf<String, String>()

    init {
        val pairs = serialized.split(PARAM_SEPARATOR)
        for (pair in pairs) {
            val keyValue = pair.split(KEY_VALUE_SEPARATOR).toMutableList()
            if (keyValue.size != 2) {
                Log.error("[ParamPackage] Invalid key pair $keyValue")
                continue
            }

            keyValue.forEachIndexed { i: Int, _: String ->
                keyValue[i] = keyValue[i].replace(KEY_VALUE_SEPARATOR_ESCAPE, KEY_VALUE_SEPARATOR)
                keyValue[i] = keyValue[i].replace(PARAM_SEPARATOR_ESCAPE, PARAM_SEPARATOR)
                keyValue[i] = keyValue[i].replace(ESCAPE_CHARACTER_ESCAPE, ESCAPE_CHARACTER)
            }

            set(keyValue[0], keyValue[1])
        }
    }

    constructor(params: List<Pair<String, String>>) : this() {
        params.forEach {
            data[it.first] = it.second
        }
    }

    fun serialize(): String {
        if (data.isEmpty()) {
            return EMPTY_PLACEHOLDER
        }

        val result = StringBuilder()
        data.forEach {
            val keyValue = mutableListOf(it.key, it.value)
            keyValue.forEachIndexed { i, _ ->
                keyValue[i] = keyValue[i].replace(ESCAPE_CHARACTER, ESCAPE_CHARACTER_ESCAPE)
                keyValue[i] = keyValue[i].replace(PARAM_SEPARATOR, PARAM_SEPARATOR_ESCAPE)
                keyValue[i] = keyValue[i].replace(KEY_VALUE_SEPARATOR, KEY_VALUE_SEPARATOR_ESCAPE)
            }
            result.append("${keyValue[0]}$KEY_VALUE_SEPARATOR${keyValue[1]}$PARAM_SEPARATOR")
        }
        return result.removeSuffix(PARAM_SEPARATOR).toString()
    }

    fun get(key: String, defaultValue: String): String =
        if (has(key)) {
            data[key]!!
        } else {
            Log.debug("[ParamPackage] key $key not found")
            defaultValue
        }

    fun get(key: String, defaultValue: Int): Int =
        if (has(key)) {
            try {
                data[key]!!.toInt()
            } catch (e: NumberFormatException) {
                Log.debug("[ParamPackage] failed to convert ${data[key]!!} to int")
                defaultValue
            }
        } else {
            Log.debug("[ParamPackage] key $key not found")
            defaultValue
        }

    private fun Int.toBoolean(): Boolean =
        if (this == 1) {
            true
        } else if (this == 0) {
            false
        } else {
            throw Exception("Tried to convert a value to a boolean that was not 0 or 1!")
        }

    fun get(key: String, defaultValue: Boolean): Boolean =
        if (has(key)) {
            try {
                get(key, if (defaultValue) 1 else 0).toBoolean()
            } catch (e: Exception) {
                Log.debug("[ParamPackage] failed to convert ${data[key]!!} to boolean")
                defaultValue
            }
        } else {
            Log.debug("[ParamPackage] key $key not found")
            defaultValue
        }

    fun get(key: String, defaultValue: Float): Float =
        if (has(key)) {
            try {
                data[key]!!.toFloat()
            } catch (e: NumberFormatException) {
                Log.debug("[ParamPackage] failed to convert ${data[key]!!} to float")
                defaultValue
            }
        } else {
            Log.debug("[ParamPackage] key $key not found")
            defaultValue
        }

    fun set(key: String, value: String) {
        data[key] = value
    }

    fun set(key: String, value: Int) {
        data[key] = value.toString()
    }

    fun Boolean.toInt(): Int = if (this) 1 else 0
    fun set(key: String, value: Boolean) {
        data[key] = value.toInt().toString()
    }

    fun set(key: String, value: Float) {
        data[key] = value.toString()
    }

    fun has(key: String): Boolean = data.containsKey(key)

    fun erase(key: String) = data.remove(key)

    fun clear() = data.clear()
}