tock-translator-core.2.0.0.source-code.I18n.kt Maven / Gradle / Ivy
/*
* Copyright (C) 2017 VSCT
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.vsct.tock.translator
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAccessor
import java.util.Locale
val defaultUserInterface: UserInterfaceType = UserInterfaceType.textChat
/**
* Format a [TemporalAccessor] this the specified [dateFormatPattern] used to create a [DateTimeFormatter].
*/
infix fun TemporalAccessor?.by(dateFormatPattern: String): DateTemplate = by(DateTimeFormatter.ofPattern(dateFormatPattern))
/**
* Format a [TemporalAccessor] this the specified [DateTimeFormatter].
*/
infix fun TemporalAccessor?.by(formatter: DateTimeFormatter): DateTemplate = DateTemplate(this, formatter)
/**
* Format a [TemporalAccessor] this the specified [DateTimeFormatterProvider].
*/
infix fun TemporalAccessor?.by(formatterProvider: DateTimeFormatterProvider): DateTemplate = DateTemplate(this, formatterProvider)
/**
* To immediately format this date with the given locale.
*/
fun TemporalAccessor?.formatWith(formatter: DateTimeFormatter, locale: Locale): CharSequence? = if (this == null) null else by(formatter).formatTo(locale)
/**
* To immediately format this date with the given locale.
*/
fun TemporalAccessor?.formatWith(formatterProvider: DateTimeFormatterProvider, locale: Locale): CharSequence? = if (this == null) null else by(formatterProvider).formatTo(locale)
/**
* Transform this char sequence in a [RawString] - ie a not-to-translate String.
*/
val CharSequence.raw: RawString get() = RawString(this)
/**
* Is this char sequence containing SSML?
*/
fun CharSequence.isSSML(): Boolean = contains("")
/**
* Split a char sequence to a list of char sequence.
*/
fun CharSequence.splitToCharSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List {
return if (this is TextAndVoiceTranslatedString) {
splitToCharSequence(*delimiters, ignoreCase = ignoreCase, limit = limit)
} else {
rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map { subSequence(it) }
}
}
//copied from Strings.kt ->
private class DelimitedRangesSequence(private val input: CharSequence, private val startIndex: Int, private val limit: Int, private val getNextMatch: CharSequence.(Int) -> Pair?) : Sequence {
override fun iterator(): Iterator = object : Iterator {
var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue
var currentStartIndex: Int = startIndex.coerceIn(0, input.length)
var nextSearchIndex: Int = currentStartIndex
var nextItem: IntRange? = null
var counter: Int = 0
private fun calcNext() {
if (nextSearchIndex < 0) {
nextState = 0
nextItem = null
} else {
if (limit > 0 && ++counter >= limit || nextSearchIndex > input.length) {
nextItem = currentStartIndex..input.lastIndex
nextSearchIndex = -1
} else {
val match = input.getNextMatch(nextSearchIndex)
if (match == null) {
nextItem = currentStartIndex..input.lastIndex
nextSearchIndex = -1
} else {
val (index, length) = match
nextItem = currentStartIndex..index - 1
currentStartIndex = index + length
nextSearchIndex = currentStartIndex + if (length == 0) 1 else 0
}
}
nextState = 1
}
}
override fun next(): IntRange {
if (nextState == -1)
calcNext()
if (nextState == 0)
throw NoSuchElementException()
val result = nextItem as IntRange
// Clean next to avoid keeping reference on yielded instance
nextItem = null
nextState = -1
return result
}
override fun hasNext(): Boolean {
if (nextState == -1)
calcNext()
return nextState == 1
}
}
}
private fun CharSequence.rangesDelimitedBy(delimiters: Array, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence {
require(limit >= 0, { "Limit must be non-negative, but was $limit." })
val delimitersList = delimiters.asList()
return DelimitedRangesSequence(this, startIndex, limit, { start -> findAnyOf(delimitersList, start, ignoreCase = ignoreCase, last = false)?.let { it.first to it.second.length } })
}
private fun CharSequence.findAnyOf(strings: Collection, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? {
if (!ignoreCase && strings.size == 1) {
val string = strings.single()
val index = if (!last) indexOf(string, startIndex) else lastIndexOf(string, startIndex)
return if (index < 0) null else index to string
}
val indices = if (!last) startIndex.coerceAtLeast(0)..length else startIndex.coerceAtMost(lastIndex) downTo 0
if (this is String) {
for (index in indices) {
val matchingString = strings.firstOrNull { it.regionMatches(0, this, index, it.length, ignoreCase) }
if (matchingString != null)
return index to matchingString
}
} else {
for (index in indices) {
val matchingString = strings.firstOrNull { it.regionMatchesImpl(0, this, index, it.length, ignoreCase) }
if (matchingString != null)
return index to matchingString
}
}
return null
}
internal fun CharSequence.regionMatchesImpl(thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, ignoreCase: Boolean): Boolean {
if ((otherOffset < 0) || (thisOffset < 0) || (thisOffset > this.length - length)
|| (otherOffset > other.length - length)) {
return false
}
for (index in 0..length - 1) {
if (!this[thisOffset + index].equals(other[otherOffset + index], ignoreCase))
return false
}
return true
}
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
internal fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).indexOf(ch.toInt(), fromIndex)
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
internal fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).lastIndexOf(ch.toInt(), fromIndex)
© 2015 - 2024 Weber Informatics LLC | Privacy Policy