mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
优化
This commit is contained in:
parent
45c88716f3
commit
d6ff9d06ad
@ -93,7 +93,9 @@ object AppWebDav {
|
||||
val names = arrayListOf<String>()
|
||||
authorization?.let {
|
||||
var files = WebDav(rootWebDavUrl, it).listFiles()
|
||||
files = files.reversed()
|
||||
files = files.sortedWith { o1, o2 ->
|
||||
AlphanumComparator.compare(o1.displayName, o2.displayName)
|
||||
}.reversed()
|
||||
files.forEach { webDav ->
|
||||
val name = webDav.displayName
|
||||
if (name.startsWith("backup")) {
|
||||
|
@ -68,7 +68,7 @@ class ContentProcessor private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun upRemoveSameTitle() {
|
||||
private fun upRemoveSameTitle() {
|
||||
val book = appDb.bookDao.getBookByOrigin(bookName, bookOrigin) ?: return
|
||||
removeSameTitleCache.clear()
|
||||
val files = BookHelp.getChapterFiles(book).filter {
|
||||
|
@ -13,7 +13,7 @@ import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.jsoup.nodes.Entities
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import org.mozilla.javascript.NativeObject
|
||||
import java.net.URL
|
||||
import java.util.regex.Pattern
|
||||
@ -49,6 +49,8 @@ class AnalyzeRule(
|
||||
private var objectChangedJS = false
|
||||
private var objectChangedJP = false
|
||||
|
||||
private val stringRuleCache = hashMapOf<String, List<SourceRule>>()
|
||||
|
||||
@JvmOverloads
|
||||
fun setContent(content: Any?, baseUrl: String? = null): AnalyzeRule {
|
||||
if (content == null) throw AssertionError("内容不可空(Content cannot be null)")
|
||||
@ -128,7 +130,7 @@ class AnalyzeRule(
|
||||
@JvmOverloads
|
||||
fun getStringList(rule: String?, mContent: Any? = null, isUrl: Boolean = false): List<String>? {
|
||||
if (rule.isNullOrEmpty()) return null
|
||||
val ruleList = splitSourceRule(rule, false)
|
||||
val ruleList = splitSourceRuleCacheString(rule)
|
||||
return getStringList(ruleList, mContent, isUrl)
|
||||
}
|
||||
|
||||
@ -208,13 +210,13 @@ class AnalyzeRule(
|
||||
@JvmOverloads
|
||||
fun getString(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false): String {
|
||||
if (TextUtils.isEmpty(ruleStr)) return ""
|
||||
val ruleList = splitSourceRule(ruleStr)
|
||||
val ruleList = splitSourceRuleCacheString(ruleStr)
|
||||
return getString(ruleList, mContent, isUrl)
|
||||
}
|
||||
|
||||
fun getString(ruleStr: String?, unescape: Boolean): String {
|
||||
if (TextUtils.isEmpty(ruleStr)) return ""
|
||||
val ruleList = splitSourceRule(ruleStr)
|
||||
val ruleList = splitSourceRuleCacheString(ruleStr)
|
||||
return getString(ruleList, unescape = unescape)
|
||||
}
|
||||
|
||||
@ -270,13 +272,7 @@ class AnalyzeRule(
|
||||
}
|
||||
if (result == null) result = ""
|
||||
val str = if (unescape) {
|
||||
kotlin.runCatching {
|
||||
Entities.unescape(result.toString())
|
||||
}.onFailure {
|
||||
log("Entities.unescape() error\n${it.localizedMessage}")
|
||||
}.getOrElse {
|
||||
result.toString()
|
||||
}
|
||||
StringEscapeUtils.unescapeHtml3(result.toString())
|
||||
} else result.toString()
|
||||
if (isUrl) {
|
||||
return if (str.isBlank()) {
|
||||
@ -414,6 +410,21 @@ class AnalyzeRule(
|
||||
return vResult
|
||||
}
|
||||
|
||||
/**
|
||||
* getString 类规则缓存
|
||||
*/
|
||||
fun splitSourceRuleCacheString(ruleStr: String?) : List<SourceRule> {
|
||||
if (ruleStr.isNullOrEmpty()) return emptyList()
|
||||
val cacheRule = stringRuleCache[ruleStr]
|
||||
return if (cacheRule != null) {
|
||||
cacheRule
|
||||
} else {
|
||||
val rules = splitSourceRule(ruleStr)
|
||||
stringRuleCache[ruleStr] = rules
|
||||
rules
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分解规则生成规则列表
|
||||
*/
|
||||
|
@ -23,6 +23,7 @@ import io.legado.app.lib.webdav.WebDavException
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import org.jsoup.nodes.Entities
|
||||
import splitties.init.appCtx
|
||||
import java.io.*
|
||||
@ -133,11 +134,7 @@ object LocalBook {
|
||||
}
|
||||
if (book.isEpub) {
|
||||
content = content?.replace("<img", "< img", true) ?: return null
|
||||
return kotlin.runCatching {
|
||||
Entities.unescape(content)
|
||||
}.onFailure {
|
||||
AppLog.put("HTML实体解码失败\n${it.localizedMessage}", it)
|
||||
}.getOrDefault(content)
|
||||
return StringEscapeUtils.unescapeHtml3(content)
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
76
app/src/main/java/io/legado/app/utils/AlphanumComparator.kt
Normal file
76
app/src/main/java/io/legado/app/utils/AlphanumComparator.kt
Normal file
@ -0,0 +1,76 @@
|
||||
package io.legado.app.utils
|
||||
|
||||
object AlphanumComparator : Comparator<String> {
|
||||
|
||||
override fun compare(s1: String, s2: String): Int {
|
||||
var thisMarker = 0
|
||||
var thatMarker = 0
|
||||
val s1Length = s1.length
|
||||
val s2Length = s2.length
|
||||
|
||||
while (thisMarker < s1Length && thatMarker < s2Length) {
|
||||
val thisChunk = getChunk(s1, s1Length, thisMarker)
|
||||
thisMarker += thisChunk.length
|
||||
|
||||
val thatChunk = getChunk(s2, s2Length, thatMarker)
|
||||
thatMarker += thatChunk.length
|
||||
|
||||
// If both chunks contain numeric characters, sort them numerically.
|
||||
var result: Int
|
||||
if (isDigit(thisChunk[0]) && isDigit(thatChunk[0])) {
|
||||
// Simple chunk comparison by length.
|
||||
val thisChunkLength = thisChunk.length
|
||||
result = thisChunkLength - thatChunk.length
|
||||
// If equal, the first different number counts.
|
||||
if (result == 0) {
|
||||
for (i in 0 until thisChunkLength) {
|
||||
result = thisChunk[i] - thatChunk[i]
|
||||
if (result != 0) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = thisChunk.compareTo(thatChunk)
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return s1Length - s2Length
|
||||
}
|
||||
|
||||
private fun getChunk(string: String, length: Int, marker: Int): String {
|
||||
var current = marker
|
||||
val chunk = StringBuilder()
|
||||
var c = string[current]
|
||||
chunk.append(c)
|
||||
current++
|
||||
if (isDigit(c)) {
|
||||
while (current < length) {
|
||||
c = string[current]
|
||||
if (!isDigit(c)) {
|
||||
break
|
||||
}
|
||||
chunk.append(c)
|
||||
current++
|
||||
}
|
||||
} else {
|
||||
while (current < length) {
|
||||
c = string[current]
|
||||
if (isDigit(c)) {
|
||||
break
|
||||
}
|
||||
chunk.append(c)
|
||||
current++
|
||||
}
|
||||
}
|
||||
return chunk.toString()
|
||||
}
|
||||
|
||||
private fun isDigit(ch: Char): Boolean {
|
||||
return ch in '0'..'9'
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package io.legado.app.utils
|
||||
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import org.jsoup.nodes.Entities
|
||||
import java.net.URL
|
||||
import java.util.regex.Pattern
|
||||
@ -31,12 +32,8 @@ object HtmlFormatter {
|
||||
.replace("\\s*\\n+\\s*".toRegex(), "\n ")
|
||||
.replace("^[\\n\\s]+".toRegex(), " ")
|
||||
.replace("[\\n\\s]+$".toRegex(), "")
|
||||
.let { s ->
|
||||
kotlin.runCatching {
|
||||
Entities.unescape(s)
|
||||
}.onFailure {
|
||||
AppLog.put("Entities.unescape() error\n${it.localizedMessage}", it)
|
||||
}.getOrDefault(s)
|
||||
.let {
|
||||
StringEscapeUtils.unescapeHtml3(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,12 +9,16 @@ import java.io.InputStream
|
||||
@Suppress("unused")
|
||||
object MD5Utils {
|
||||
|
||||
private val MD5Digester by lazy {
|
||||
DigestUtil.digester("MD5")
|
||||
}
|
||||
|
||||
fun md5Encode(str: String?): String {
|
||||
return DigestUtil.digester("MD5").digestHex(str)
|
||||
return MD5Digester.digestHex(str)
|
||||
}
|
||||
|
||||
fun md5Encode(inputStream: InputStream): String {
|
||||
return DigestUtil.digester("MD5").digestHex(inputStream)
|
||||
return MD5Digester.digestHex(inputStream)
|
||||
}
|
||||
|
||||
fun md5Encode16(str: String): String {
|
||||
|
@ -32,9 +32,11 @@ abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngi
|
||||
200 -> {
|
||||
context.setBindings(bindings, 200)
|
||||
}
|
||||
|
||||
100 -> {
|
||||
context.setBindings(bindings, 100)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalArgumentException("Invalid scope value.")
|
||||
}
|
||||
@ -84,15 +86,11 @@ abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngi
|
||||
}
|
||||
|
||||
override fun getScriptContext(bindings: Bindings): ScriptContext {
|
||||
val ctx = SimpleScriptContext()
|
||||
val ctx = SimpleScriptContext(bindings, context.errorWriter, context.reader, context.writer)
|
||||
val gs = getBindings(200)
|
||||
if (gs != null) {
|
||||
ctx.setBindings(gs, 200)
|
||||
}
|
||||
ctx.setBindings(bindings, 100)
|
||||
ctx.reader = context.reader
|
||||
ctx.writer = context.writer
|
||||
ctx.errorWriter = context.errorWriter
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,14 @@ import java.io.Reader
|
||||
import java.io.Writer
|
||||
import java.util.*
|
||||
|
||||
open class SimpleScriptContext : ScriptContext {
|
||||
private var engineScope: Bindings = SimpleBindings()
|
||||
override var errorWriter: Writer = PrintWriter(System.err, true)
|
||||
private var globalScope: Bindings? = null
|
||||
override var reader: Reader = InputStreamReader(System.`in`)
|
||||
open class SimpleScriptContext(
|
||||
private var engineScope: Bindings = SimpleBindings(),
|
||||
override var errorWriter: Writer = PrintWriter(System.err, true),
|
||||
override var reader: Reader = InputStreamReader(System.`in`),
|
||||
override var writer: Writer = PrintWriter(System.out, true)
|
||||
) : ScriptContext {
|
||||
private var globalScope: Bindings? = null
|
||||
|
||||
override fun setBindings(bindings: Bindings?, scope: Int) {
|
||||
when (scope) {
|
||||
100 -> {
|
||||
@ -24,6 +26,7 @@ open class SimpleScriptContext : ScriptContext {
|
||||
engineScope = bindings
|
||||
return
|
||||
}
|
||||
|
||||
200 -> {
|
||||
globalScope = bindings
|
||||
return
|
||||
@ -46,6 +49,7 @@ open class SimpleScriptContext : ScriptContext {
|
||||
100 -> {
|
||||
return engineScope[name]
|
||||
}
|
||||
|
||||
200 -> {
|
||||
return globalScope?.get(name)
|
||||
}
|
||||
@ -58,6 +62,7 @@ open class SimpleScriptContext : ScriptContext {
|
||||
100 -> {
|
||||
return getBindings(100)?.remove(name)
|
||||
}
|
||||
|
||||
200 -> {
|
||||
return getBindings(200)?.remove(name)
|
||||
}
|
||||
@ -71,6 +76,7 @@ open class SimpleScriptContext : ScriptContext {
|
||||
engineScope[name] = value
|
||||
return
|
||||
}
|
||||
|
||||
200 -> {
|
||||
globalScope?.put(name, value)
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user