Merge branch 'main' of ssh://git.jaytux.com:35000/jay-tux/simd.jaytux.com

This commit is contained in:
2025-04-27 18:50:47 +02:00
31 changed files with 1599 additions and 95 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
{
@ -130,4 +132,14 @@ Gets the details for a single, specific intrinsic. The following data is returne
}
]
}
```
```
### `GET /version`
Gets version information for the data. The following data is returned:
```json
{
"intelVersion": "M.m.p (Major.minor.patch version as reported by Intel)",
"intelUpdate": "yyyy-MM-dd (date of Intel's last update prior to scraping)",
"scrapeDate": "yyyy-MM-dd (date of last update)"
}
```

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)
}

View File

@ -8,7 +8,7 @@
<logger name="io.netty" level="warn" />
<logger name="ch.qos.logback" level="warn" />
<root level="trace">
<root level="warn">
<appender-ref ref="APPENDER"/>
</root>
</configuration>
</configuration>