Slight API change, finalization of (desktop) UI (gotta do mobile web view still)

This commit is contained in:
2025-04-27 17:58:36 +02:00
parent 67577a9197
commit 073048f7b3
42 changed files with 133 additions and 501 deletions

View File

@ -76,12 +76,14 @@ Gets a (paginated) list of all C/C++(-like) types used by the intrinsics. The ty
Searches the database using the given filters. The filters are passed as query parameters, and can be combined. All filters are optional. The following filters are available:
- `name=[string]`: searches based on the name of the intrinsic; employs fuzzy-search (using `LIKE %it%`)
- `return=[string]`: searches based on the return type of the intrinsic; exact search only
- `cpuid=[string]`: searches based on the CPUID of the intrinsic; exact search only
- `tech=[string]`: searches based on the technology of the intrinsic; exact search only
- `category=[string]`: searches based on the category of the intrinsic; exact search only
- `cpuid=[*]`: searches based on the CPUID of the intrinsic; exact search only
- `tech=[*]`: searches based on the technology of the intrinsic; exact search only
- `category=[*]`: searches based on the category of the intrinsic; exact search only
- `desc=[string]`: searches based on the description of the intrinsic; employs fuzzy-search (using `LIKE %it%`)
- `page=[int]`: specifies the page number to return (default is 0)
Parameters marked by `[*]` are JSON-lists (so you should pass them as `cpuid=["PREFETCHI", "SSE2"]`). They are considered to be OR-ed together (i.e. the results will contain a mix of all intrinsics matching either of the CPUIDs (from the example)).
Passing no filters is equivalent to using `GET /all`, and data is returned in the same format:
```json
{

View File

@ -1,6 +1,7 @@
package com.jaytux.simd.data
import com.fleeksoft.ksoup.Ksoup
import com.fleeksoft.ksoup.parser.Parser
import com.jaytux.simd.data.IntrinsicInstructions.xed
import kotlinx.coroutines.coroutineScope
import kotlinx.datetime.*
@ -84,6 +85,7 @@ object Loader {
suspend fun loadXml(xmlFile: String): XmlData = coroutineScope {
val xml = Ksoup.parseXml(File(xmlFile).readText(Charsets.UTF_8))
Parser.xmlParser()
val cppTypes = mutableSetOf<String>()
val techs = mutableSetOf<String>()
@ -158,13 +160,13 @@ object Loader {
args += argName to type
}
val desc = it.getElementsByTag("description").firstOrNull()?.text()
val desc = it.getElementsByTag("description").firstOrNull()?.wholeText()?.trim()
if(desc == null) {
errors += "Missing description element for intrinsic $name"
return@forEachIndexed
}
val op = it.getElementsByTag("operation").firstOrNull()?.text()
val op = it.getElementsByTag("operation").firstOrNull()?.wholeText()?.trim()
val insn = mutableListOf<Triple<String, String, String?>>()
it.getElementsByTag("instruction").forEachIndexed { i, ins ->

View File

@ -4,13 +4,17 @@ import com.jaytux.simd.data.*
import com.jaytux.simd.server.RouteCache.register
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.jetbrains.exposed.dao.UUIDEntity
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.like
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.*
@ -60,32 +64,46 @@ fun Routing.installGetAll() {
fun Routing.installSearch() {
getPagedRequest("/search", "Search for intrinsics matching certain filters", { 100 }, { IntrinsicSummary(it[Intrinsics.id].value, it[Intrinsics.mnemonic]) }) {
fun <T : UUIDEntity> resolveAny(key: String, finder: (String) -> SizedIterable<T>): List<EntityID<UUID>>? {
return call.request.queryParameters[key]?.let {
try {
val list = Json.decodeFromString<List<String>>(it)
list.map {
finder(it).firstOrNull()?.id
?: throw HttpError("Unknown $key: ${list.joinToString(", ")}")
}
}
catch(e: HttpError) {
throw e
}
catch(e: Exception) {
throw HttpError("Malformed $key parameter: $it")
}
}
}
val name = call.request.queryParameters["name"]
val returnType = call.request.queryParameters["return"]?.let {
CppType.find { CppTypes.name eq it }.firstOrNull()
?: throw HttpError("Unknown return type: $it")
}
val cpuid = call.request.queryParameters["cpuid"]?.let {
CPUID.find { CPUIDs.name eq it }.firstOrNull()
?: throw HttpError("Unknown CPUID: $it")
}
val tech = call.request.queryParameters["tech"]?.let {
Tech.find { Techs.name eq it }.firstOrNull()
?: throw HttpError("Unknown tech: $it")
}
val category = call.request.queryParameters["category"]?.let {
Category.find { Categories.name eq it }.firstOrNull()
?: throw HttpError("Unknown category: $it")
}
val anyCpuid = resolveAny("cpuid") { CPUID.find { CPUIDs.name eq it } }
val anyTech = resolveAny("tech") { Tech.find { Techs.name eq it } }
val anyCat = resolveAny("category") { Category.find { Categories.name eq it } }
val desc = call.request.queryParameters["desc"]
var results = Intrinsics.selectAll()
name?.let { results = results.where { Intrinsics.mnemonic like "%$it%" } }
returnType?.let { results = results.where { Intrinsics.returnType eq it.id } }
cpuid?.let { results = results.where { Intrinsics.cpuid eq it.id } }
tech?.let { results = results.where { Intrinsics.tech eq it.id } }
category?.let { results = results.where { Intrinsics.category eq it.id } }
desc?.let { results = results.where { Intrinsics.description like "%$it%" } }
var results = Intrinsics.selectAll().where {
val build = listOf(
name?.let { Intrinsics.mnemonic like "%$it%" },
returnType?.let { Intrinsics.returnType eq it.id },
anyCpuid?.let { Intrinsics.cpuid inList it },
anyTech?.let { Intrinsics.tech inList it },
anyCat?.let { Intrinsics.category inList it },
desc?.let { Intrinsics.description like "%$it%" }
).filterNotNull()
build.fold(Op.TRUE as Op<Boolean>, { acc, op -> op and acc })
}
results.orderAsc(Intrinsics.mnemonic)
}