summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorSaikari <[email protected]>2026-01-17 19:10:32 +0300
committerSaikari <[email protected]>2026-01-17 19:10:32 +0300
commit769cd6b401b4f33790d5361c2eb16aa3aac8fa1c (patch)
tree6a66a9b6a15f0e72e8eb81e5f2613b105f6e7929 /core/src
parent6ace7f776cd21b91323e00d1bfc61f6722a7961d (diff)
try build netbsd
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/string/case.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/core/src/xmake/string/case.c b/core/src/xmake/string/case.c
index 1bf1c022d..06b98de41 100644
--- a/core/src/xmake/string/case.c
+++ b/core/src/xmake/string/case.c
@@ -30,6 +30,8 @@
*/
#include "prefix.h"
#include <ctype.h>
+/* Include Tbox platform header for spinlocks */
+#include "tbox/platform/spinlock.h"
#ifdef TB_CONFIG_OS_WINDOWS
# include <windows.h>
@@ -38,10 +40,22 @@
# include <locale.h>
# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
# include <xlocale.h>
+# elif defined(__NetBSD__)
+# include <string.h>
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
+ * globals
+ */
+
+/*
+ * Define a static Tbox spinlock.
+ * setlocale() is not thread-safe on Windows or Linux, so we protect it globally.
+ */
+static tb_spinlock_t g_locale_lock = TB_SPINLOCK_INIT;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
@@ -70,9 +84,9 @@ static tb_bool_t xm_string_case_ascii(lua_State* lua, tb_char_t const* str, tb_s
for (i = 0; i < size; i++) {
tb_byte_t c = (tb_byte_t)str[i];
if (lower) {
- buf[i] = (tb_char_t)tolower(c);
+ buf[i] = (tb_char_t)(isupper(c)? tolower(c) : c);
} else {
- buf[i] = (tb_char_t)toupper(c);
+ buf[i] = (tb_char_t)(islower(c)? toupper(c) : c);
}
}
@@ -117,6 +131,41 @@ static tb_bool_t xm_string_case_unicode(lua_State* lua, tb_char_t const* str, tb
}
}
#else
+# if defined(__NetBSD__)
+ // NetBSD lacks of uselocale
+ tb_spinlock_enter(&g_locale_lock);
+
+ char* saved_locale = tb_null;
+ char* current_locale = setlocale(LC_CTYPE, NULL);
+
+ if (current_locale) {
+ size_t len = tb_strlen(current_locale);
+ saved_locale = (char*)tb_malloc_bytes(len + 1);
+ if (saved_locale) {
+ tb_memcpy(saved_locale, current_locale, len + 1);
+ }
+ }
+
+ if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
+ setlocale(LC_CTYPE, "UTF-8");
+ }
+
+ for (i = 0; i < wn; i++) {
+ tb_wchar_t wc = wb[i];
+ if (lower) {
+ if (!iswlower(wc)) wb[i] = towlower(wc);
+ } else {
+ if (!iswupper(wc)) wb[i] = towupper(wc);
+ }
+ }
+
+ if (saved_locale) {
+ setlocale(LC_CTYPE, saved_locale);
+ tb_free(saved_locale);
+ }
+
+ tb_spinlock_leave(&g_locale_lock);
+# else
// POSIX Thread-Safe Implementation
locale_t new_loc = newlocale(LC_CTYPE_MASK, "en_US.UTF-8", (locale_t)0);
if (!new_loc) {
@@ -136,6 +185,7 @@ static tb_bool_t xm_string_case_unicode(lua_State* lua, tb_char_t const* str, tb
uselocale(old_loc);
freelocale(new_loc);
}
+# endif
#endif
// Convert Wide Char back to UTF-8