Skip to content

Commit c0c5439

Browse files
committed
WIP QDBM multiple implementations
1 parent 5aa0f10 commit c0c5439

File tree

12 files changed

+876
-0
lines changed

12 files changed

+876
-0
lines changed

.github/workflows/build-linux.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ jobs:
2525
restore-keys: |
2626
${{ runner.os }}-konan-
2727
28+
- name: QDBM install
29+
run: |
30+
sudo apt-get install libqdbm-dev
31+
2832
- name: Linux build
2933
run: |
3034
./gradlew build publishToMavenLocal --no-daemon --stacktrace

multiplatform-settings/api/multiplatform-settings.klib.api

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,102 @@ final class com.russhwolf.settings/StorageSettings : com.russhwolf.settings/Sett
225225
final fun remove(kotlin/String) // com.russhwolf.settings/StorageSettings.remove|remove(kotlin.String){}[0]
226226
}
227227

228+
// Targets: [linuxX64]
229+
final class com.russhwolf.settings/QdbmDepotSettings : com.russhwolf.settings/Settings { // com.russhwolf.settings/QdbmDepotSettings|null[0]
230+
constructor <init>(kotlin/String) // com.russhwolf.settings/QdbmDepotSettings.<init>|<init>(kotlin.String){}[0]
231+
232+
final val keys // com.russhwolf.settings/QdbmDepotSettings.keys|{}keys[0]
233+
final fun <get-keys>(): kotlin.collections/Set<kotlin/String> // com.russhwolf.settings/QdbmDepotSettings.keys.<get-keys>|<get-keys>(){}[0]
234+
final val size // com.russhwolf.settings/QdbmDepotSettings.size|{}size[0]
235+
final fun <get-size>(): kotlin/Int // com.russhwolf.settings/QdbmDepotSettings.size.<get-size>|<get-size>(){}[0]
236+
237+
final fun clear() // com.russhwolf.settings/QdbmDepotSettings.clear|clear(){}[0]
238+
final fun getBoolean(kotlin/String, kotlin/Boolean): kotlin/Boolean // com.russhwolf.settings/QdbmDepotSettings.getBoolean|getBoolean(kotlin.String;kotlin.Boolean){}[0]
239+
final fun getBooleanOrNull(kotlin/String): kotlin/Boolean? // com.russhwolf.settings/QdbmDepotSettings.getBooleanOrNull|getBooleanOrNull(kotlin.String){}[0]
240+
final fun getDouble(kotlin/String, kotlin/Double): kotlin/Double // com.russhwolf.settings/QdbmDepotSettings.getDouble|getDouble(kotlin.String;kotlin.Double){}[0]
241+
final fun getDoubleOrNull(kotlin/String): kotlin/Double? // com.russhwolf.settings/QdbmDepotSettings.getDoubleOrNull|getDoubleOrNull(kotlin.String){}[0]
242+
final fun getFloat(kotlin/String, kotlin/Float): kotlin/Float // com.russhwolf.settings/QdbmDepotSettings.getFloat|getFloat(kotlin.String;kotlin.Float){}[0]
243+
final fun getFloatOrNull(kotlin/String): kotlin/Float? // com.russhwolf.settings/QdbmDepotSettings.getFloatOrNull|getFloatOrNull(kotlin.String){}[0]
244+
final fun getInt(kotlin/String, kotlin/Int): kotlin/Int // com.russhwolf.settings/QdbmDepotSettings.getInt|getInt(kotlin.String;kotlin.Int){}[0]
245+
final fun getIntOrNull(kotlin/String): kotlin/Int? // com.russhwolf.settings/QdbmDepotSettings.getIntOrNull|getIntOrNull(kotlin.String){}[0]
246+
final fun getLong(kotlin/String, kotlin/Long): kotlin/Long // com.russhwolf.settings/QdbmDepotSettings.getLong|getLong(kotlin.String;kotlin.Long){}[0]
247+
final fun getLongOrNull(kotlin/String): kotlin/Long? // com.russhwolf.settings/QdbmDepotSettings.getLongOrNull|getLongOrNull(kotlin.String){}[0]
248+
final fun getString(kotlin/String, kotlin/String): kotlin/String // com.russhwolf.settings/QdbmDepotSettings.getString|getString(kotlin.String;kotlin.String){}[0]
249+
final fun getStringOrNull(kotlin/String): kotlin/String? // com.russhwolf.settings/QdbmDepotSettings.getStringOrNull|getStringOrNull(kotlin.String){}[0]
250+
final fun hasKey(kotlin/String): kotlin/Boolean // com.russhwolf.settings/QdbmDepotSettings.hasKey|hasKey(kotlin.String){}[0]
251+
final fun putBoolean(kotlin/String, kotlin/Boolean) // com.russhwolf.settings/QdbmDepotSettings.putBoolean|putBoolean(kotlin.String;kotlin.Boolean){}[0]
252+
final fun putDouble(kotlin/String, kotlin/Double) // com.russhwolf.settings/QdbmDepotSettings.putDouble|putDouble(kotlin.String;kotlin.Double){}[0]
253+
final fun putFloat(kotlin/String, kotlin/Float) // com.russhwolf.settings/QdbmDepotSettings.putFloat|putFloat(kotlin.String;kotlin.Float){}[0]
254+
final fun putInt(kotlin/String, kotlin/Int) // com.russhwolf.settings/QdbmDepotSettings.putInt|putInt(kotlin.String;kotlin.Int){}[0]
255+
final fun putLong(kotlin/String, kotlin/Long) // com.russhwolf.settings/QdbmDepotSettings.putLong|putLong(kotlin.String;kotlin.Long){}[0]
256+
final fun putString(kotlin/String, kotlin/String) // com.russhwolf.settings/QdbmDepotSettings.putString|putString(kotlin.String;kotlin.String){}[0]
257+
final fun remove(kotlin/String) // com.russhwolf.settings/QdbmDepotSettings.remove|remove(kotlin.String){}[0]
258+
}
259+
260+
// Targets: [linuxX64]
261+
final class com.russhwolf.settings/QdbmRelicSettings : com.russhwolf.settings/Settings { // com.russhwolf.settings/QdbmRelicSettings|null[0]
262+
constructor <init>(kotlin/String) // com.russhwolf.settings/QdbmRelicSettings.<init>|<init>(kotlin.String){}[0]
263+
264+
final val keys // com.russhwolf.settings/QdbmRelicSettings.keys|{}keys[0]
265+
final fun <get-keys>(): kotlin.collections/Set<kotlin/String> // com.russhwolf.settings/QdbmRelicSettings.keys.<get-keys>|<get-keys>(){}[0]
266+
final val size // com.russhwolf.settings/QdbmRelicSettings.size|{}size[0]
267+
final fun <get-size>(): kotlin/Int // com.russhwolf.settings/QdbmRelicSettings.size.<get-size>|<get-size>(){}[0]
268+
269+
final fun clear() // com.russhwolf.settings/QdbmRelicSettings.clear|clear(){}[0]
270+
final fun getBoolean(kotlin/String, kotlin/Boolean): kotlin/Boolean // com.russhwolf.settings/QdbmRelicSettings.getBoolean|getBoolean(kotlin.String;kotlin.Boolean){}[0]
271+
final fun getBooleanOrNull(kotlin/String): kotlin/Boolean? // com.russhwolf.settings/QdbmRelicSettings.getBooleanOrNull|getBooleanOrNull(kotlin.String){}[0]
272+
final fun getDouble(kotlin/String, kotlin/Double): kotlin/Double // com.russhwolf.settings/QdbmRelicSettings.getDouble|getDouble(kotlin.String;kotlin.Double){}[0]
273+
final fun getDoubleOrNull(kotlin/String): kotlin/Double? // com.russhwolf.settings/QdbmRelicSettings.getDoubleOrNull|getDoubleOrNull(kotlin.String){}[0]
274+
final fun getFloat(kotlin/String, kotlin/Float): kotlin/Float // com.russhwolf.settings/QdbmRelicSettings.getFloat|getFloat(kotlin.String;kotlin.Float){}[0]
275+
final fun getFloatOrNull(kotlin/String): kotlin/Float? // com.russhwolf.settings/QdbmRelicSettings.getFloatOrNull|getFloatOrNull(kotlin.String){}[0]
276+
final fun getInt(kotlin/String, kotlin/Int): kotlin/Int // com.russhwolf.settings/QdbmRelicSettings.getInt|getInt(kotlin.String;kotlin.Int){}[0]
277+
final fun getIntOrNull(kotlin/String): kotlin/Int? // com.russhwolf.settings/QdbmRelicSettings.getIntOrNull|getIntOrNull(kotlin.String){}[0]
278+
final fun getLong(kotlin/String, kotlin/Long): kotlin/Long // com.russhwolf.settings/QdbmRelicSettings.getLong|getLong(kotlin.String;kotlin.Long){}[0]
279+
final fun getLongOrNull(kotlin/String): kotlin/Long? // com.russhwolf.settings/QdbmRelicSettings.getLongOrNull|getLongOrNull(kotlin.String){}[0]
280+
final fun getString(kotlin/String, kotlin/String): kotlin/String // com.russhwolf.settings/QdbmRelicSettings.getString|getString(kotlin.String;kotlin.String){}[0]
281+
final fun getStringOrNull(kotlin/String): kotlin/String? // com.russhwolf.settings/QdbmRelicSettings.getStringOrNull|getStringOrNull(kotlin.String){}[0]
282+
final fun hasKey(kotlin/String): kotlin/Boolean // com.russhwolf.settings/QdbmRelicSettings.hasKey|hasKey(kotlin.String){}[0]
283+
final fun putBoolean(kotlin/String, kotlin/Boolean) // com.russhwolf.settings/QdbmRelicSettings.putBoolean|putBoolean(kotlin.String;kotlin.Boolean){}[0]
284+
final fun putDouble(kotlin/String, kotlin/Double) // com.russhwolf.settings/QdbmRelicSettings.putDouble|putDouble(kotlin.String;kotlin.Double){}[0]
285+
final fun putFloat(kotlin/String, kotlin/Float) // com.russhwolf.settings/QdbmRelicSettings.putFloat|putFloat(kotlin.String;kotlin.Float){}[0]
286+
final fun putInt(kotlin/String, kotlin/Int) // com.russhwolf.settings/QdbmRelicSettings.putInt|putInt(kotlin.String;kotlin.Int){}[0]
287+
final fun putLong(kotlin/String, kotlin/Long) // com.russhwolf.settings/QdbmRelicSettings.putLong|putLong(kotlin.String;kotlin.Long){}[0]
288+
final fun putString(kotlin/String, kotlin/String) // com.russhwolf.settings/QdbmRelicSettings.putString|putString(kotlin.String;kotlin.String){}[0]
289+
final fun remove(kotlin/String) // com.russhwolf.settings/QdbmRelicSettings.remove|remove(kotlin.String){}[0]
290+
}
291+
292+
// Targets: [linuxX64]
293+
final class com.russhwolf.settings/QdbmVillaSettings : com.russhwolf.settings/Settings { // com.russhwolf.settings/QdbmVillaSettings|null[0]
294+
constructor <init>(kotlin/String) // com.russhwolf.settings/QdbmVillaSettings.<init>|<init>(kotlin.String){}[0]
295+
296+
final val keys // com.russhwolf.settings/QdbmVillaSettings.keys|{}keys[0]
297+
final fun <get-keys>(): kotlin.collections/Set<kotlin/String> // com.russhwolf.settings/QdbmVillaSettings.keys.<get-keys>|<get-keys>(){}[0]
298+
final val size // com.russhwolf.settings/QdbmVillaSettings.size|{}size[0]
299+
final fun <get-size>(): kotlin/Int // com.russhwolf.settings/QdbmVillaSettings.size.<get-size>|<get-size>(){}[0]
300+
301+
final fun clear() // com.russhwolf.settings/QdbmVillaSettings.clear|clear(){}[0]
302+
final fun getBoolean(kotlin/String, kotlin/Boolean): kotlin/Boolean // com.russhwolf.settings/QdbmVillaSettings.getBoolean|getBoolean(kotlin.String;kotlin.Boolean){}[0]
303+
final fun getBooleanOrNull(kotlin/String): kotlin/Boolean? // com.russhwolf.settings/QdbmVillaSettings.getBooleanOrNull|getBooleanOrNull(kotlin.String){}[0]
304+
final fun getDouble(kotlin/String, kotlin/Double): kotlin/Double // com.russhwolf.settings/QdbmVillaSettings.getDouble|getDouble(kotlin.String;kotlin.Double){}[0]
305+
final fun getDoubleOrNull(kotlin/String): kotlin/Double? // com.russhwolf.settings/QdbmVillaSettings.getDoubleOrNull|getDoubleOrNull(kotlin.String){}[0]
306+
final fun getFloat(kotlin/String, kotlin/Float): kotlin/Float // com.russhwolf.settings/QdbmVillaSettings.getFloat|getFloat(kotlin.String;kotlin.Float){}[0]
307+
final fun getFloatOrNull(kotlin/String): kotlin/Float? // com.russhwolf.settings/QdbmVillaSettings.getFloatOrNull|getFloatOrNull(kotlin.String){}[0]
308+
final fun getInt(kotlin/String, kotlin/Int): kotlin/Int // com.russhwolf.settings/QdbmVillaSettings.getInt|getInt(kotlin.String;kotlin.Int){}[0]
309+
final fun getIntOrNull(kotlin/String): kotlin/Int? // com.russhwolf.settings/QdbmVillaSettings.getIntOrNull|getIntOrNull(kotlin.String){}[0]
310+
final fun getLong(kotlin/String, kotlin/Long): kotlin/Long // com.russhwolf.settings/QdbmVillaSettings.getLong|getLong(kotlin.String;kotlin.Long){}[0]
311+
final fun getLongOrNull(kotlin/String): kotlin/Long? // com.russhwolf.settings/QdbmVillaSettings.getLongOrNull|getLongOrNull(kotlin.String){}[0]
312+
final fun getString(kotlin/String, kotlin/String): kotlin/String // com.russhwolf.settings/QdbmVillaSettings.getString|getString(kotlin.String;kotlin.String){}[0]
313+
final fun getStringOrNull(kotlin/String): kotlin/String? // com.russhwolf.settings/QdbmVillaSettings.getStringOrNull|getStringOrNull(kotlin.String){}[0]
314+
final fun hasKey(kotlin/String): kotlin/Boolean // com.russhwolf.settings/QdbmVillaSettings.hasKey|hasKey(kotlin.String){}[0]
315+
final fun putBoolean(kotlin/String, kotlin/Boolean) // com.russhwolf.settings/QdbmVillaSettings.putBoolean|putBoolean(kotlin.String;kotlin.Boolean){}[0]
316+
final fun putDouble(kotlin/String, kotlin/Double) // com.russhwolf.settings/QdbmVillaSettings.putDouble|putDouble(kotlin.String;kotlin.Double){}[0]
317+
final fun putFloat(kotlin/String, kotlin/Float) // com.russhwolf.settings/QdbmVillaSettings.putFloat|putFloat(kotlin.String;kotlin.Float){}[0]
318+
final fun putInt(kotlin/String, kotlin/Int) // com.russhwolf.settings/QdbmVillaSettings.putInt|putInt(kotlin.String;kotlin.Int){}[0]
319+
final fun putLong(kotlin/String, kotlin/Long) // com.russhwolf.settings/QdbmVillaSettings.putLong|putLong(kotlin.String;kotlin.Long){}[0]
320+
final fun putString(kotlin/String, kotlin/String) // com.russhwolf.settings/QdbmVillaSettings.putString|putString(kotlin.String;kotlin.String){}[0]
321+
final fun remove(kotlin/String) // com.russhwolf.settings/QdbmVillaSettings.remove|remove(kotlin.String){}[0]
322+
}
323+
228324
// Targets: [mingwX64]
229325
final class com.russhwolf.settings/RegistrySettings : com.russhwolf.settings/Settings { // com.russhwolf.settings/RegistrySettings|null[0]
230326
constructor <init>(kotlin/String) // com.russhwolf.settings/RegistrySettings.<init>|<init>(kotlin.String){}[0]

multiplatform-settings/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
1717
* limitations under the License.
1818
*/
1919

20+
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
21+
2022
plugins {
2123
id("standard-configuration")
2224
id("module-publication")
@@ -27,6 +29,11 @@ standardConfig {
2729
}
2830

2931
kotlin {
32+
targets.getByName<KotlinNativeTarget>("linuxX64") {
33+
compilations["main"].cinterops.create("qdbm-depot")
34+
compilations["main"].cinterops.create("qdbm-relic")
35+
compilations["main"].cinterops.create("qdbm-villa")
36+
}
3037
@OptIn(ExperimentalKotlinGradlePluginApi::class)
3138
compilerOptions {
3239
freeCompilerArgs.add("-Xexpect-actual-classes")
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2022 Russell Wolf
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.russhwolf.settings
18+
19+
import com.russhwolf.settings.cinterop.qdbm.depot.DEPOT
20+
import com.russhwolf.settings.cinterop.qdbm.depot.DP_DOVER
21+
import com.russhwolf.settings.cinterop.qdbm.depot.DP_OCREAT
22+
import com.russhwolf.settings.cinterop.qdbm.depot.DP_OREADER
23+
import com.russhwolf.settings.cinterop.qdbm.depot.DP_OWRITER
24+
import com.russhwolf.settings.cinterop.qdbm.depot.dpclose
25+
import com.russhwolf.settings.cinterop.qdbm.depot.dpecode
26+
import com.russhwolf.settings.cinterop.qdbm.depot.dperrmsg
27+
import com.russhwolf.settings.cinterop.qdbm.depot.dpget
28+
import com.russhwolf.settings.cinterop.qdbm.depot.dpiterinit
29+
import com.russhwolf.settings.cinterop.qdbm.depot.dpiternext
30+
import com.russhwolf.settings.cinterop.qdbm.depot.dpopen
31+
import com.russhwolf.settings.cinterop.qdbm.depot.dpout
32+
import com.russhwolf.settings.cinterop.qdbm.depot.dpput
33+
import kotlinx.cinterop.CPointer
34+
import kotlinx.cinterop.ExperimentalForeignApi
35+
import kotlinx.cinterop.MemScope
36+
import kotlinx.cinterop.memScoped
37+
import kotlinx.cinterop.toKString
38+
39+
// TODO clean up error checking?
40+
// TODO allow specifying directory
41+
@OptIn(ExperimentalForeignApi::class)
42+
@ExperimentalSettingsImplementation
43+
public class QdbmDepotSettings(private val path: String) : Settings {
44+
45+
override val keys: Set<String>
46+
get() = depotOperation { depot ->
47+
depot.foldKeys(mutableListOf<String>()) { list, key -> list.apply { add(key) } }.toSet()
48+
}
49+
50+
override val size: Int get() = depotOperation { depot -> depot.foldKeys(0) { size, _ -> size + 1 } }
51+
52+
public override fun clear(): Unit = depotOperation { depot -> depot.forEachKey { dpout(depot, it, -1) } }
53+
public override fun remove(key: String): Unit = depotOperation { depot -> dpout(depot, key, -1) }
54+
public override fun hasKey(key: String): Boolean = depotOperation { depot ->
55+
depot.forEachKey { if (key == it) return true }
56+
return false
57+
}
58+
59+
public override fun putInt(key: String, value: Int): Unit = saveString(key, value.toString())
60+
public override fun getInt(key: String, defaultValue: Int): Int = getIntOrNull(key) ?: defaultValue
61+
public override fun getIntOrNull(key: String): Int? = loadString(key)?.toInt()
62+
63+
public override fun putLong(key: String, value: Long): Unit = saveString(key, value.toString())
64+
public override fun getLong(key: String, defaultValue: Long): Long = getLongOrNull(key) ?: defaultValue
65+
public override fun getLongOrNull(key: String): Long? = loadString(key)?.toLong()
66+
67+
public override fun putString(key: String, value: String): Unit = saveString(key, value)
68+
public override fun getString(key: String, defaultValue: String): String = getStringOrNull(key) ?: defaultValue
69+
public override fun getStringOrNull(key: String): String? = loadString(key)
70+
71+
public override fun putFloat(key: String, value: Float): Unit = saveString(key, value.toString())
72+
public override fun getFloat(key: String, defaultValue: Float): Float = getFloatOrNull(key) ?: defaultValue
73+
public override fun getFloatOrNull(key: String): Float? = loadString(key)?.toFloat()
74+
75+
public override fun putDouble(key: String, value: Double): Unit = saveString(key, value.toString())
76+
public override fun getDouble(key: String, defaultValue: Double): Double = getDoubleOrNull(key) ?: defaultValue
77+
public override fun getDoubleOrNull(key: String): Double? = loadString(key)?.toDouble()
78+
79+
public override fun putBoolean(key: String, value: Boolean): Unit = saveString(key, value.toString())
80+
public override fun getBoolean(key: String, defaultValue: Boolean): Boolean = getBooleanOrNull(key) ?: defaultValue
81+
public override fun getBooleanOrNull(key: String): Boolean? = loadString(key)?.toBoolean()
82+
83+
private inline fun saveString(key: String, value: String): Unit = depotOperation { depot ->
84+
dpput(depot, key, -1, value, -1, DP_DOVER.toInt())
85+
}
86+
87+
private inline fun loadString(key: String): String? = depotOperation { depot ->
88+
val output = dpget(depot, key, -1, 0, -1, null)
89+
output?.toKString()
90+
}
91+
92+
private inline fun CPointer<DEPOT>.forEachKey(block: (key: String) -> Unit) {
93+
val depot = this
94+
if (dpiterinit(depot) != 0) {
95+
while (true) {
96+
val key = dpiternext(depot, null)?.toKString()
97+
if (key != null) {
98+
block(key)
99+
} else {
100+
break
101+
}
102+
}
103+
}
104+
}
105+
106+
private inline fun <A> CPointer<DEPOT>.foldKeys(initial: A, block: (accumulator: A, key: String) -> A): A {
107+
var accumulator = initial
108+
forEachKey { accumulator = block(accumulator, it) }
109+
return accumulator
110+
}
111+
112+
private inline fun <T> depotOperation(action: MemScope.(depot: CPointer<DEPOT>) -> T): T = memScoped {
113+
val depot = dpopen(path, (DP_OWRITER or DP_OREADER or DP_OCREAT).toInt(), 0)
114+
if (depot == null) {
115+
val message = dperrmsg(dpecode)?.toKString()
116+
error("error on depot open: $message")
117+
}
118+
val out = action(depot)
119+
dpclose(depot)
120+
out
121+
}
122+
}

0 commit comments

Comments
 (0)