<commit_before>package org.jetbrains.ktor.features

import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.util.CaseInsensitiveMap
import java.util.logging.*

object ContentTypeByExtension {
    private val contentTypesFileName = "mimelist.csv"

    val contentTypesByExtensions: Map<String, List<ContentType>> by lazy {
        processRecords { ext, contentType -> ext to contentType }.let { records -> CaseInsensitiveMap<List<ContentType>>(records.size).apply { putAll(records) } }
    }

    private val extensionsByContentType: Map<ContentType, List<String>> by lazy {
        processRecords { ext, contentType -> contentType to ext }
    }

    fun lookupByPath(path: String): List<ContentType> {
        val slashIndex = path.lastIndexOfAny("/\\".toCharArray())
        val index = path.indexOf('.', startIndex = slashIndex + 1)
        return lookupByExtension(path.substring(index + 1))
    }

    fun lookupByExtension(ext: String): List<ContentType> {
        var current = ext.removePrefix(".")
        while (current.isNotEmpty()) {
            val type = contentTypesByExtensions[current]
            if (type != null) {
                return type
            }<commit_msg>Avoid excess contentions on getting type by file extension<commit_after>package org.jetbrains.ktor.features

import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.util.CaseInsensitiveMap
import java.util.logging.*

object ContentTypeByExtension {
    private val contentTypesFileName = "mimelist.csv"

    val contentTypesByExtensions: Map<String, List<ContentType>> by lazy(LazyThreadSafetyMode.PUBLICATION) {
        processRecords { ext, contentType -> ext to contentType }.let { records -> CaseInsensitiveMap<List<ContentType>>(records.size).apply { putAll(records) } }
    }

    private val extensionsByContentType: Map<ContentType, List<String>> by lazy {
        processRecords { ext, contentType -> contentType to ext }
    }

    fun lookupByPath(path: String): List<ContentType> {
        val slashIndex = path.lastIndexOfAny("/\\".toCharArray())
        val index = path.indexOf('.', startIndex = slashIndex + 1)
        return lookupByExtension(path.substring(index + 1))
    }

    fun lookupByExtension(ext: String): List<ContentType> {
        var current = ext.removePrefix(".")
        while (current.isNotEmpty()) {
            val type = contentTypesByExtensions[current]
            if (type != null) {
                return type
            }
{'fraction_non_alphanumeric': 0.10849248273059732, 'fraction_numerical': 0.0016253555465258025, 'mean_word_length': 3.2743055555555554, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1792922', 'n_tokens_mistral': 691, 'n_tokens_neox': 665, 'n_words': 160}