From 821254837628cf9e6f295448fd8ecc48a850e54d Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 2 May 2026 11:35:03 +0900 Subject: [PATCH] Use std::string_view in Encoding and AGS::draw_text() --- src/android/nact_android.cpp | 2 +- src/debugger/dap_frontend.cpp | 2 +- src/emscripten/nact_emscripten.cpp | 2 +- src/encoding.cpp | 71 ++++++++++++++++-------------- src/encoding.h | 19 +++----- src/sys/ags.h | 3 +- src/sys/ags_text.cpp | 10 ++--- src/sys/nact.cpp | 10 ++--- src/sys/nact_sys1.cpp | 16 +++---- src/sys/nact_sys2.cpp | 10 ++--- src/sys/nact_sys3.cpp | 10 ++--- src/win/nact_win.cpp | 2 +- 12 files changed, 80 insertions(+), 77 deletions(-) diff --git a/src/android/nact_android.cpp b/src/android/nact_android.cpp index b60f3ea..b4ab8b1 100644 --- a/src/android/nact_android.cpp +++ b/src/android/nact_android.cpp @@ -12,7 +12,7 @@ void NACT::text_dialog() if (!jni.env()) return; - std::string oldstr = encoding->toUtf8(tvar[tvar_index - 1].c_str()); + std::string oldstr = encoding->toUtf8(tvar[tvar_index - 1]); jstring joldstr = jni.env()->NewStringUTF(oldstr.c_str()); if (!joldstr) { WARNING("Failed to allocate a string"); diff --git a/src/debugger/dap_frontend.cpp b/src/debugger/dap_frontend.cpp index a0f1e31..0a404d9 100644 --- a/src/debugger/dap_frontend.cpp +++ b/src/debugger/dap_frontend.cpp @@ -417,7 +417,7 @@ private: } value = value.substr(1, value.size() - 2); - g_nact->set_string(index, g_nact->encoding->fromUtf8(value.c_str())); + g_nact->set_string(index, g_nact->encoding->fromUtf8(value)); resp["success"] = true; resp["body"] = { diff --git a/src/emscripten/nact_emscripten.cpp b/src/emscripten/nact_emscripten.cpp index f6e40f2..8cb8f5a 100644 --- a/src/emscripten/nact_emscripten.cpp +++ b/src/emscripten/nact_emscripten.cpp @@ -19,7 +19,7 @@ Uint32 custom_event_type = static_cast(-1); void NACT::text_dialog() { static char buf[256]; - std::string oldstr = encoding->toUtf8(tvar[tvar_index - 1].c_str()); + std::string oldstr = encoding->toUtf8(tvar[tvar_index - 1]); int ok = EM_ASM_({ var r = xsystem35.shell.inputString("文字列を入力してください", UTF8ToString($0), $1); if (r) { diff --git a/src/encoding.cpp b/src/encoding.cpp index 9062cdd..49cf049 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -16,20 +16,25 @@ public: return is_2byte(first_byte) ? 2 : 1; } - int next_codepoint(const unsigned char** s) override + int next_codepoint(std::string_view& s) override { - int code = *(*s)++; - if (is_2byte(code)) - code = (code << 8) | (uint8)*(*s)++; + int code = (unsigned char)s[0]; + if (is_2byte(code)) { + code = (code << 8) | (unsigned char)s[1]; + s.remove_prefix(2); + } else { + s.remove_prefix(1); + } return sjis_to_unicode(code); } - std::string fromUtf8(const char* str) override + std::string fromUtf8(std::string_view sv) override { - unsigned char* src = (unsigned char*)str; + auto src = reinterpret_cast(sv.data()); + auto end = src + sv.size(); std::string result; - while (*src) { + while (src < end) { if (*src <= 0x7f) { result += *src++; continue; @@ -44,7 +49,7 @@ public: src += 3; } else { result += '?'; - do src++; while ((*src & 0xc0) == 0x80); + do src++; while (src < end && (*src & 0xc0) == 0x80); continue; } @@ -63,12 +68,13 @@ public: return result; } - std::string toUtf8(const char* str) override + std::string toUtf8(std::string_view sv) override { - unsigned char* src = (unsigned char*)str; + auto src = reinterpret_cast(sv.data()); + auto end = src + sv.size(); std::string result; - while (*src) { + while (src < end) { if (*src <= 0x7f) { result += *src++; continue; @@ -145,52 +151,53 @@ public: return 4; } - int next_codepoint(const unsigned char** str) override + int next_codepoint(std::string_view& s) override { int code; - const unsigned char *s = *str; + unsigned char c = s[0]; - if (*s <= 0x7f) { - code = *s++; - } else if (*s <= 0xbf) { + if (c <= 0x7f) { + code = c; + s.remove_prefix(1); + } else if (c <= 0xbf) { // Invalid UTF-8 sequence code = '?'; - s++; - } else if (*s <= 0xdf) { + s.remove_prefix(1); + } else if (c <= 0xdf) { code = (s[0] & 0x1f) << 6 | (s[1] & 0x3f); - s += 2; - } else if (*s <= 0xef) { + s.remove_prefix(2); + } else if (c <= 0xef) { code = (s[0] & 0xf) << 12 | (s[1] & 0x3f) << 6 | (s[2] & 0x3f); - s += 3; - } else if (*s <= 0xf7) { + s.remove_prefix(3); + } else if (c <= 0xf7) { code = (s[0] & 0x7) << 18 | (s[1] & 0x3f) << 12 | (s[2] & 0x3f) << 6 | (s[3] & 0x3f); - s += 4; + s.remove_prefix(4); } else { code = 0xfffd; // REPLACEMENT CHARACTER - s++; - while (0x80 <= *s && *s <= 0xbf) - s++; + s.remove_prefix(1); + while (!s.empty() && 0x80 <= (unsigned char)s[0] && (unsigned char)s[0] <= 0xbf) + s.remove_prefix(1); } - *str = s; return code; } - std::string fromUtf8(const char* s) override + std::string fromUtf8(std::string_view s) override { return std::string(s); } - std::string toUtf8(const char* s) override + std::string toUtf8(std::string_view s) override { return std::string(s); } }; -int Encoding::mbslen(const unsigned char* s) +int Encoding::mbslen(std::string_view s) { int len = 0; - while (*s) { - s += mblen(*s); + while (!s.empty()) { + int n = mblen((unsigned char)s[0]); + s.remove_prefix(n); len++; } return len; diff --git a/src/encoding.h b/src/encoding.h index fbc98f4..45aca70 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -3,6 +3,7 @@ #include #include +#include // Gaiji characters are mapped to Unicode Private Use Area U+E000-U+E0BB. const int GAIJI_FIRST = 0xE000; @@ -14,23 +15,17 @@ class Encoding { virtual ~Encoding() = default; - // Returns Unicode codepoint of the first character of *s, and advances *s + // Returns Unicode codepoint of the first character of s, and advances s // to the next character. - virtual int next_codepoint(const unsigned char** s) = 0; - int next_codepoint(const char** s) { - return next_codepoint(reinterpret_cast(s)); - } + virtual int next_codepoint(std::string_view& s) = 0; // Determines the byte length of a character based on the first byte. virtual int mblen(unsigned char first_byte) = 0; // Returns the number of characters in s. - int mbslen(const unsigned char* s); - int mbslen(const char* s) { - return mbslen(reinterpret_cast(s)); - } + int mbslen(std::string_view s); - // Convert from/to utf-8 encoding. Caller must free() the returned buffer. - virtual std::string fromUtf8(const char* s) = 0; - virtual std::string toUtf8(const char* s) = 0; + // Convert from/to utf-8 encoding. + virtual std::string fromUtf8(std::string_view s) = 0; + virtual std::string toUtf8(std::string_view s) = 0; }; #endif // _ENCODING_H_ diff --git a/src/sys/ags.h b/src/sys/ags.h index 9eadece..7950180 100644 --- a/src/sys/ags.h +++ b/src/sys/ags.h @@ -8,6 +8,7 @@ #define _AGS_H_ #include +#include #include #include #include @@ -129,7 +130,7 @@ public: void box_line(int dest, int sx, int sy, int ex, int ey, uint8 color); void draw_window(int sx, int sy, int ex, int ey, bool frame, uint8 frame_color, uint8 back_color); - void draw_text(const char* string, bool text_wait = false); + void draw_text(std::string_view string, bool text_wait = false); void clear_text_window(int index, bool erase); bool return_text_line(int index); diff --git a/src/sys/ags_text.cpp b/src/sys/ags_text.cpp index d6f66aa..0fe87a0 100644 --- a/src/sys/ags_text.cpp +++ b/src/sys/ags_text.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include "ags.h" #include "nact.h" #include "encoding.h" @@ -348,9 +348,9 @@ int convert_to_hankaku(int code) } // namespace -void AGS::draw_text(const char* string, bool text_wait) +void AGS::draw_text(std::string_view string, bool text_wait) { - if (!*string) + if (string.empty()) return; uint8 antialias_cache[256*7]; if (antialias) @@ -376,8 +376,8 @@ void AGS::draw_text(const char* string, bool text_wait) // Adjust dest_y if the font height is larger than the specified size. dest_y -= (ascent - descent - ctx.font_size) / 2; - while (*string) { - int code = g_nact->encoding->next_codepoint(&string); + while (!string.empty()) { + int code = g_nact->encoding->next_codepoint(string); if(draw_hankaku) { code = convert_to_hankaku(code); } else { diff --git a/src/sys/nact.cpp b/src/sys/nact.cpp index 8ff84f5..6d47406 100644 --- a/src/sys/nact.cpp +++ b/src/sys/nact.cpp @@ -376,8 +376,8 @@ void NACT::cmd_set_verbobj() verb_obj = true; TRACE("[%x,%s,%s:", addr, - encoding->toUtf8(caption_verb[verb].c_str()).c_str(), - encoding->toUtf8(caption_obj[obj].c_str()).c_str()); + encoding->toUtf8(caption_verb[verb]).c_str(), + encoding->toUtf8(caption_obj[obj]).c_str()); } void NACT::cmd_set_verbobj2() @@ -393,8 +393,8 @@ void NACT::cmd_set_verbobj2() verb_obj = true; TRACE(":%d,%x,%s,%s:", condition, addr, - encoding->toUtf8(caption_verb[verb].c_str()).c_str(), - encoding->toUtf8(caption_obj[obj].c_str()).c_str()); + encoding->toUtf8(caption_verb[verb]).c_str(), + encoding->toUtf8(caption_obj[obj]).c_str()); } void NACT::cmd_a() @@ -474,7 +474,7 @@ void NACT::cmd_x() TRACE("X %d:", index); if(1 <= index && index <= 10) { - ags->draw_text(tvar[index - 1].c_str()); + ags->draw_text(tvar[index - 1]); } } diff --git a/src/sys/nact_sys1.cpp b/src/sys/nact_sys1.cpp index 6bf9768..ea51ed2 100644 --- a/src/sys/nact_sys1.cpp +++ b/src/sys/nact_sys1.cpp @@ -199,7 +199,7 @@ top: // 1ページ内に全て表示できる for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i].c_str()); + ags->draw_text(caption_verb[i]); ags->menu.newline(); id[index++] = i; } @@ -208,7 +208,7 @@ top: top2: for(int i = page; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i].c_str()); + ags->draw_text(caption_verb[i]); ags->menu.newline(); id[index++] = i; } @@ -223,7 +223,7 @@ top2: goto top2; } // 次のページを追加 - ags->draw_text(strings.next_page.c_str()); + ags->draw_text(strings.next_page); ags->menu.newline(); id[index++] = -1; } @@ -281,20 +281,20 @@ top: // 1ページ内に全て表示できる for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i].c_str()); + ags->draw_text(caption_obj[i]); ags->menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back.c_str()); + ags->draw_text(strings.back); ags->menu.newline(); id[index++] = 0; } else { top2: for(int i = page; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i].c_str()); + ags->draw_text(caption_obj[i]); ags->menu.newline(); id[index++] = i; } @@ -309,12 +309,12 @@ top2: goto top2; } // 戻るを追加 - ags->draw_text(strings.back.c_str()); + ags->draw_text(strings.back); ags->menu.newline(); id[index++] = 0; // 次のページを追加 - ags->draw_text(strings.next_page.c_str()); + ags->draw_text(strings.next_page); ags->menu.newline(); id[index++] = -1; } diff --git a/src/sys/nact_sys2.cpp b/src/sys/nact_sys2.cpp index c3b656a..1a2c217 100644 --- a/src/sys/nact_sys2.cpp +++ b/src/sys/nact_sys2.cpp @@ -279,7 +279,7 @@ void NACT_Sys2::cmd_open_verb() for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i].c_str()); + ags->draw_text(caption_verb[i]); ags->menu.newline(); id[index++] = i; } @@ -330,13 +330,13 @@ void NACT_Sys2::cmd_open_obj(int verb) for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i].c_str()); + ags->draw_text(caption_obj[i]); ags->menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back.c_str()); + ags->draw_text(strings.back); ags->menu.newline(); id[index++] = 0; ags->draw_menu = false; @@ -778,8 +778,8 @@ void NACT_Sys2::cmd_y() case 228: case 229: if(1 <= param && param <= 10) { - ags->draw_text(tvar[param - 1].c_str()); - int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1].c_str()); + ags->draw_text(tvar[param - 1]); + int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); if (padlen > 0) { char pad[10] = " "; pad[padlen] = '\0'; diff --git a/src/sys/nact_sys3.cpp b/src/sys/nact_sys3.cpp index ca515c7..2d4ddcc 100644 --- a/src/sys/nact_sys3.cpp +++ b/src/sys/nact_sys3.cpp @@ -159,7 +159,7 @@ void NACT_Sys3::cmd_open_verb() for(int i = 0; i < MAX_VERB; i++) { if(chk[i]) { - ags->draw_text(caption_verb[i].c_str()); + ags->draw_text(caption_verb[i]); ags->menu.newline(); id[index++] = i; } @@ -210,13 +210,13 @@ void NACT_Sys3::cmd_open_obj(int verb) for(int i = 0; i < MAX_OBJ; i++) { if(chk[i]) { - ags->draw_text(caption_obj[i].c_str()); + ags->draw_text(caption_obj[i]); ags->menu.newline(); id[index++] = i; } } // 戻るを追加 - ags->draw_text(strings.back.c_str()); + ags->draw_text(strings.back); ags->menu.newline(); id[index++] = 0; ags->draw_menu = false; @@ -953,8 +953,8 @@ void NACT_Sys3::exec_y(int cmd, int param) case 228: case 229: { - ags->draw_text(tvar[param - 1].c_str()); - int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1].c_str()); + ags->draw_text(tvar[param - 1]); + int padlen = cmd - 220 - encoding->mbslen(tvar[param - 1]); if (padlen > 0) { char pad[10] = " "; pad[padlen] = '\0'; diff --git a/src/win/nact_win.cpp b/src/win/nact_win.cpp index 95d0a4e..14b6b4b 100644 --- a/src/win/nact_win.cpp +++ b/src/win/nact_win.cpp @@ -93,7 +93,7 @@ void NACT::text_dialog() swprintf_s(wstring, 64, L"文字列を入力してください(最大%d文字)", g_nact->tvar_maxlen); SetWindowTextW(GetDlgItem(hDlg, IDC_TEXT), wstring); - std::string oldstr = g_nact->encoding->toUtf8(g_nact->tvar[g_nact->tvar_index - 1].c_str()); + std::string oldstr = g_nact->encoding->toUtf8(g_nact->tvar[g_nact->tvar_index - 1]); MultiByteToWideChar(CP_UTF8, 0, oldstr.c_str(), -1, wstring, 64); SetWindowTextW(GetDlgItem(hDlg, IDC_EDITBOX), wstring); EnableWindow(GetDlgItem(hDlg, IDOK), oldstr[0] != '\0');