Bläddra i källkod

正则匹配替换成com.google.re2j
自带的正则匹配超时无法取消

kunfei 4 år sedan
förälder
incheckning
f3e05711f0

+ 3 - 0
app/build.gradle

@@ -212,6 +212,9 @@ dependencies {
     //implementation('com.github.gedoor:rhino-android:1.8')
     implementation(fileTree(dir: 'lib', include: ['rhino-*.jar']))
 
+    //正则匹配,android自带的正则匹配出现超时问题无法处理
+    implementation('com.google.re2j:re2j:1.7')
+
     //网络
     implementation('com.squareup.okhttp3:okhttp:4.10.0')
     implementation(fileTree(dir: 'cronetlib', include: ['*.jar', '*.aar']))

+ 3 - 4
app/src/main/java/io/legado/app/data/entities/BookChapter.kt

@@ -100,10 +100,9 @@ data class BookChapter(
                 if (item.pattern.isNotEmpty()) {
                     try {
                         val mDisplayTitle = if (item.isRegex) {
-                            displayTitle.replace(
-                                item.pattern.toRegex(),
-                                item.replacement,
-                                item.getValidTimeoutMillisecond()
+                            displayTitle.replaceRegex(
+                                item.pattern,
+                                item.replacement
                             )
                         } else {
                             displayTitle.replace(item.pattern, item.replacement)

+ 5 - 6
app/src/main/java/io/legado/app/help/book/ContentProcessor.kt

@@ -9,7 +9,7 @@ import io.legado.app.data.entities.ReplaceRule
 import io.legado.app.exception.RegexTimeoutException
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.ReadBookConfig
-import io.legado.app.utils.replace
+import io.legado.app.utils.replaceRegex
 import io.legado.app.utils.stackTraceStr
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.CancellationException
@@ -134,17 +134,16 @@ class ContentProcessor private constructor(
         return contents
     }
 
-    suspend fun replaceContent(content: String): String {
+    fun replaceContent(content: String): String {
         var mContent = content
         mContent = mContent.lines().joinToString("\n") { it.trim() }
         getContentReplaceRules().forEach { item ->
             if (item.pattern.isNotEmpty()) {
                 try {
                     mContent = if (item.isRegex) {
-                        mContent.replace(
-                            item.pattern.toRegex(),
-                            item.replacement,
-                            item.getValidTimeoutMillisecond()
+                        mContent.replaceRegex(
+                            item.pattern,
+                            item.replacement
                         )
                     } else {
                         mContent.replace(item.pattern, item.replacement)

+ 18 - 49
app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@@ -1,64 +1,33 @@
 package io.legado.app.utils
 
 import android.util.Log
-import androidx.core.os.postDelayed
+import com.google.re2j.Pattern
 import com.script.SimpleBindings
 import io.legado.app.constant.AppConst
-import io.legado.app.exception.RegexTimeoutException
-import io.legado.app.help.CrashHandler
-import io.legado.app.help.coroutine.Coroutine
-import kotlinx.coroutines.suspendCancellableCoroutine
-import splitties.init.appCtx
-import kotlin.coroutines.resume
-import kotlin.coroutines.resumeWithException
-
-private val handler by lazy { buildMainHandler() }
 
 /**
  * 带有超时检测的正则替换
  */
-suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
-    val charSequence = this@replace
+fun CharSequence.replaceRegex(regex: String, replacement: String): String {
+    val charSequence = this
     val isJs = replacement.startsWith("@js:")
     val replacement1 = if (isJs) replacement.substring(4) else replacement
-    return suspendCancellableCoroutine { block ->
-        val coroutine = Coroutine.async {
-            try {
-                val pattern = regex.toPattern()
-                val matcher = pattern.matcher(charSequence)
-                val stringBuffer = StringBuffer()
-                while (matcher.find()) {
-                    if (isJs) {
-                        val bindings = SimpleBindings()
-                        bindings["result"] = matcher.group()
-                        val jsResult =
-                            AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
-                        matcher.appendReplacement(stringBuffer, jsResult)
-                    } else {
-                        matcher.appendReplacement(stringBuffer, replacement1)
-                    }
-                }
-                matcher.appendTail(stringBuffer)
-                Log.e("regex", "end")
-                block.resume(stringBuffer.toString())
-            } catch (e: Exception) {
-                block.resumeWithException(e)
-            }
-        }
-        handler.postDelayed(timeout) {
-            if (coroutine.isActive) {
-                val timeoutMsg = "替换超时,3秒后还未结束将重启应用\n替换规则$regex\n替换内容:${this}"
-                val exception = RegexTimeoutException(timeoutMsg)
-                block.cancel(exception)
-                appCtx.longToastOnUi(timeoutMsg)
-                CrashHandler.saveCrashInfo2File(exception)
-                handler.postDelayed(3000) {
-                    if (coroutine.isActive) {
-                        appCtx.restart()
-                    }
-                }
-            }
+    val pattern = Pattern.compile(regex)
+    val matcher = pattern.matcher(charSequence)
+    val stringBuffer = StringBuffer()
+    while (matcher.find()) {
+        if (isJs) {
+            val bindings = SimpleBindings()
+            bindings["result"] = matcher.group()
+            val jsResult =
+                AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
+            matcher.appendReplacement(stringBuffer, jsResult)
+        } else {
+            matcher.appendReplacement(stringBuffer, replacement1)
         }
     }
+    matcher.appendTail(stringBuffer)
+    Log.e("regex", "end")
+    return stringBuffer.toString()
 }