branch: externals/xeft
commit 76b13ca6547092edb06d60584e8896f432c4dea0
Author: Yuan Fu <caso...@gmail.com>
Commit: Yuan Fu <caso...@gmail.com>

    Upgrade xapian-lite
    
    * xapian-lite.cc: Upgrade to latest.
---
 xapian-lite.cc | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 100 insertions(+), 3 deletions(-)

diff --git a/xapian-lite.cc b/xapian-lite.cc
index 539c15046c..e1c9499560 100644
--- a/xapian-lite.cc
+++ b/xapian-lite.cc
@@ -42,6 +42,10 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "emacs-module.h"
 #include "emacs-module-prelude.h"
 
+#if defined _WIN32
+#include <Windows.h>
+#endif
+
 using namespace std;
 
 int plugin_is_GPL_compatible;
@@ -113,6 +117,37 @@ hash_path (string path)
     }
 }
 
+#ifdef _WIN32
+static std::wstring ConvertUtf8ToWide(const std::string& str)
+{
+    int count = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 
nullptr, 0);
+    std::wstring wstr(count, 0);
+    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstr[0], 
count);
+    return wstr;
+}
+
+static std::string ConvertWideToANSI(const std::wstring& wstr)
+{
+    int count = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.length(), 
nullptr, 0, nullptr, nullptr);
+    std::string str(count, 0);
+    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], count, nullptr, 
nullptr);
+    return str;
+}
+
+static std::string GetConvertedWindowsPath(const std::string &path)
+{
+    std::string cvtPath = path;
+    // Code pages for reference 
https://learn.microsoft.com/zh-tw/windows/win32/intl/code-page-identifiers
+    if (65001 != GetACP())
+    {
+        auto wsPath = ConvertUtf8ToWide(path);
+        cvtPath = ConvertWideToANSI(wsPath);
+    }
+
+    return cvtPath;
+}
+#endif
+
 // Reindex the file at PATH, using database at DBPATH. Throws
 // cannot_open_file. Both path must be absolute. Normally only reindex
 // if file has change since last index, if FORCE is true, always
@@ -128,7 +163,13 @@ reindex_file
   struct stat st;
   time_t file_mtime;
   off_t file_size;
+
+#if defined _WIN32
+  auto cvtPath = GetConvertedWindowsPath(path);
+  if (stat (cvtPath.c_str(), &st) == 0)
+#else
   if (stat (path.c_str(), &st) == 0)
+#endif
     {
       file_mtime = st.st_mtime;
       file_size = st.st_size;
@@ -145,6 +186,10 @@ reindex_file
   // modified.
   if (dbpath != cached_dbpath)
     {
+      if (cached_dbpath != "")
+               {
+                 database.close();
+               }
       database = Xapian::WritableDatabase
         (dbpath, Xapian::DB_CREATE_OR_OPEN);
       cached_dbpath = dbpath;
@@ -212,6 +257,10 @@ query_term
   // See reindex_file for the reason for caching the database object.
   if (dbpath != cached_dbpath)
     {
+      if (cached_dbpath != "")
+               {
+                 database.close();
+               }
       database = Xapian::WritableDatabase
         (dbpath, Xapian::DB_CREATE_OR_OPEN);
       cached_dbpath = dbpath;
@@ -244,7 +293,7 @@ query_term
         (term, Xapian::QueryParser::FLAG_CJK_NGRAM
          | Xapian::QueryParser::FLAG_PARTIAL);
     }
-  
+
   Xapian::Enquire enquire (database);
   enquire.set_query (query);
 
@@ -341,7 +390,7 @@ Fxapian_lite_reindex_file
 
   emacs_value lisp_lang = nargs < 3 ? emp_intern (env, "nil") : args[2];
   emacs_value lisp_force = nargs < 4 ? emp_intern (env, "nil") : args[3];
-  
+
   string path = copy_string (env, lisp_path);
   string dbpath = copy_string (env, lisp_dbpath);
   bool force = !NILP (env, lisp_force);
@@ -349,7 +398,7 @@ Fxapian_lite_reindex_file
   string lang = NILP (env, lisp_lang) ?
     "en" : copy_string (env, lisp_lang);
   CHECK_EXIT (env);
-  
+
   // Do the work.
   bool indexed;
   try
@@ -475,6 +524,51 @@ Fxapian_lite_query_term
   return emp_funcall (env, "reverse", 1, ret);
 }
 
+static const char *xapian_lite_close_database_doc =
+  "By closing the databse, you allow other xapian-lite instances to\n"
+  "access the database. In addition, closing the database commits all the\n"
+  "pending modifications to the database done by\n"
+  "`xapian-lite-reindex-file'. (For performance reasons, modifications to\n"
+  "the database is only committed to the disk after 10000 changes or when\n"
+  "closing the database.) It’s a good idea to close the database\n"
+  "periodically so database modifications aren’t lost due to unexpected\n"
+  "Emacs crash.\n"
+  "\n"
+  "There’s no need to explicitly reconnect to the database, since any\n"
+  "subsequent access will automatically reconnect to it.\n"
+  "\n"
+  "(fn DBPATH)";
+
+static emacs_value
+Fxapian_lite_close_database
+(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
+  EMACS_NOEXCEPT
+{
+  emacs_value lisp_dbpath = args[0];
+
+  if (NILP (env,
+            emp_funcall (env, "file-name-absolute-p", 1, lisp_dbpath)))
+    {
+      emp_signal_message1 (env, "xapian-lite-file-error",
+                           "DBPATH is not a absolute path");
+      return NULL;
+    }
+
+  lisp_dbpath = emp_funcall (env, "expand-file-name", 1, lisp_dbpath);
+  string dbpath = copy_string (env, lisp_dbpath);
+
+  /* If cached_dbpath == "", there's no database to close. If dbpath
+     != cached_dbpath, the database that the user wants to close is
+     already closed. */
+  if (cached_dbpath != "" && dbpath == cached_dbpath)
+       {
+         database.close();
+         cached_dbpath = "";
+       }
+
+  return emp_intern (env, "nil");
+}
+
 int
 emacs_module_init (struct emacs_runtime *ert) EMACS_NOEXCEPT
 {
@@ -497,6 +591,9 @@ emacs_module_init (struct emacs_runtime *ert) EMACS_NOEXCEPT
   emp_define_function(env, "xapian-lite-query-term", 4, 4,
                   &Fxapian_lite_query_term,
                   xapian_lite_query_term_doc);
+  emp_define_function(env, "xapian-lite-close-database", 1, 1,
+                  &Fxapian_lite_close_database,
+                  xapian_lite_close_database_doc);
 
   emp_provide (env, "xapian-lite");
 

Reply via email to