From 710937f8df1655357d38f168f4fa8537e1328c3a Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Fri, 13 May 2016 10:16:29 +0200 Subject: [PATCH] Language ID type redeclaration for easier and safer work --- ZRCola/zrcolafrm.cpp | 24 ++-- ZRColaCompile/dbsource.cpp | 4 +- ZRColaCompile/main.cpp | 4 +- lib/libZRCola/include/zrcola/common.h | 143 ++++++++++++++++++++++- lib/libZRCola/include/zrcola/language.h | 8 +- lib/libZRCola/include/zrcola/translate.h | 2 +- lib/libZRCola/src/language.cpp | 65 +++++------ 7 files changed, 190 insertions(+), 60 deletions(-) diff --git a/ZRCola/zrcolafrm.cpp b/ZRCola/zrcolafrm.cpp index ab0f45e..e9d1195 100644 --- a/ZRCola/zrcolafrm.cpp +++ b/ZRCola/zrcolafrm.cpp @@ -60,6 +60,7 @@ wxEND_EVENT_TABLE() wxZRColaFrame::wxZRColaFrame() : m_lang_auto(true), + m_lang(ZRCola::langid_t_blank), m_hWndSource(NULL), m_chrSelect(NULL), wxZRColaFrameBase(NULL) @@ -99,7 +100,6 @@ wxZRColaFrame::wxZRColaFrame() : { // Populate language lists. - memcpy(m_lang, ZRCOLA_LANG_VOID, sizeof(m_lang)); ZRColaApp *app = ((ZRColaApp*)wxTheApp); m_toolDecompLanguage->Clear(); wxString label1_tran(_("Select %s language for decomposition")); @@ -111,7 +111,7 @@ wxZRColaFrame::wxZRColaFrame() : if (i < wxID_DECOMP_LANGUAGE_END - wxID_DECOMP_LANGUAGE_START + 1) m_menuDecompLanguage->AppendRadioItem(wxID_DECOMP_LANGUAGE_START + i, label_tran2, wxString::Format(label1_tran, (const wxStringCharType*)label_tran2)); m_toolDecompLanguage->Insert(label_tran2, i); - if (memcmp(m_lang, lang.id, sizeof(m_lang)) == 0) + if (m_lang == lang.id) m_toolDecompLanguage->Select(i); } } @@ -335,7 +335,7 @@ void wxZRColaFrame::OnDecomposedLanguageUpdate(wxUpdateUIEvent& event) { ZRColaApp *app = ((ZRColaApp*)wxTheApp); const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[event.GetId() - wxID_DECOMP_LANGUAGE_START]; - event.Check(memcmp(m_lang, lang.id, sizeof(m_lang)) == 0); + event.Check(m_lang == lang.id); } @@ -345,8 +345,8 @@ void wxZRColaFrame::OnDecomposedLanguage(wxCommandEvent& event) size_t i = event.GetId() - wxID_DECOMP_LANGUAGE_START; const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[i]; - if (memcmp(m_lang, lang.id, sizeof(m_lang)) != 0) { - memcpy(m_lang, lang.id, sizeof(m_lang)); + if (m_lang != lang.id) { + m_lang = lang.id; m_toolDecompLanguage->Select(i); // Notify composed text something changed and should re-decompose. @@ -363,8 +363,8 @@ void wxZRColaFrame::OnDecompLanguageChoice(wxCommandEvent& event) size_t i = event.GetSelection(); const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[i]; - if (memcmp(m_lang, lang.id, sizeof(m_lang)) != 0) { - memcpy(m_lang, lang.id, sizeof(m_lang)); + if (m_lang != lang.id) { + m_lang = lang.id; // Notify composed text something changed and should re-decompose. wxCommandEvent event2(wxEVT_COMMAND_TEXT_UPDATED); @@ -563,7 +563,7 @@ void wxZRColaFrame::UpdateDecomposedLanguage() // Find language on the language list. ZRCola::language_db::language *l = new ZRCola::language_db::language; - memcpy(l->id, m_lang, sizeof(l->id)); + l->id = m_lang; l->name_len = 0; ZRCola::language_db::indexLang::size_type start; m_toolDecompLanguage->SetSelection(app->m_lang_db.idxLng.find(*l, start) ? start : -1); @@ -639,7 +639,7 @@ void wxPersistentZRColaFrame::Save() const wxPersistentZRColaCharacterCatalogPanel(wnd->m_panelChrCat).Save(); SaveValue(wxT("langAuto" ), wnd->m_lang_auto); - SaveValue(wxT("lang" ), wxString::FromAscii(wnd->m_lang, sizeof(wnd->m_lang))); + SaveValue(wxT("lang" ), wxString::FromAscii(wnd->m_lang.data, _countof(wnd->m_lang.data))); wxPersistentTLW::Save(); } @@ -663,12 +663,12 @@ bool wxPersistentZRColaFrame::Restore() #endif } else if (RestoreValue(wxT("lang"), &lang) && lang.Length() == 3) { // The language was read from configuration. - memcpy(wnd->m_lang, (const char*)lang.c_str(), sizeof(wnd->m_lang)); + wnd->m_lang = lang.c_str(); } else if (!app->m_lang_db.idxLng.empty()) { const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[0]; - memcpy(wnd->m_lang, lang.id, sizeof(wnd->m_lang)); + wnd->m_lang = lang.id; } else - memcpy(wnd->m_lang, ZRCOLA_LANG_VOID, sizeof(wnd->m_lang)); + wnd->m_lang = ZRCola::langid_t_blank; wnd->UpdateDecomposedLanguage(); wxPersistentZRColaCharacterCatalogPanel(wnd->m_panelChrCat).Restore(); diff --git a/ZRColaCompile/dbsource.cpp b/ZRColaCompile/dbsource.cpp index 3cde67f..d6e1ce0 100644 --- a/ZRColaCompile/dbsource.cpp +++ b/ZRColaCompile/dbsource.cpp @@ -400,9 +400,9 @@ bool ZRCola::DBSource::GetLanguage(const ATL::CComPtr& f, ZRCola::lang _ftprintf(stderr, wxT("%s: error ZCC0081: Syntax error in \"%.*ls\" field (\"%.*ls\"). Language ID must contain ASCII characters only.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v)); return false; } - lang[i] = (char)c; + lang.data[i] = (char)c; } else - lang[i] = 0; + lang.data[i] = 0; } else break; } diff --git a/ZRColaCompile/main.cpp b/ZRColaCompile/main.cpp index 838d1dd..9cc4bc6 100644 --- a/ZRColaCompile/main.cpp +++ b/ZRColaCompile/main.cpp @@ -243,7 +243,7 @@ int _tmain(int argc, _TCHAR *argv[]) // Add language to index and data. unsigned __int32 idx = db.data.size(); for (std::wstring::size_type i = 0; i < sizeof(ZRCola::langid_t)/sizeof(unsigned __int16); i++) - db.data.push_back(((const unsigned __int16*)lang.id)[i]); + db.data.push_back(((const unsigned __int16*)lang.id.data)[i]); std::wstring::size_type n = lang.name.length(); wxASSERT_MSG(n <= 0xffff, wxT("language name too long")); db.data.push_back((unsigned __int16)n); @@ -297,7 +297,7 @@ int _tmain(int argc, _TCHAR *argv[]) unsigned __int32 idx = db.data.size(); db.data.push_back(lc.chr); for (std::wstring::size_type i = 0; i < sizeof(ZRCola::langid_t)/sizeof(unsigned __int16); i++) - db.data.push_back(((const unsigned __int16*)lc.lang)[i]); + db.data.push_back(((const unsigned __int16*)lc.lang.data)[i]); db.idxChr.push_back(idx); #ifdef ZRCOLA_LANGCHAR_LANG_IDX db.idxLng.push_back(idx); diff --git a/lib/libZRCola/include/zrcola/common.h b/lib/libZRCola/include/zrcola/common.h index 97657a8..89418b6 100644 --- a/lib/libZRCola/include/zrcola/common.h +++ b/lib/libZRCola/include/zrcola/common.h @@ -52,11 +52,6 @@ /// #define ZRCOLA_DB_ID (*(ZRCola::recordid_t*)"ZRC") -/// -/// Unknown language ID -/// -#define ZRCOLA_LANG_VOID " " - namespace ZRCola { typedef unsigned __int32 recordid_t; @@ -81,7 +76,143 @@ namespace ZRCola { /// Language ID type /// Three letter abbreviation, zero terminated /// - typedef char langid_t[4]; + struct langid_t { + char data[4]; + + inline langid_t& operator=(const langid_t &src) + { + data[0] = src.data[0]; + data[1] = src.data[1]; + data[2] = src.data[2]; + data[3] = src.data[3]; + return *this; + } + + inline langid_t& operator=(const char *src) + { + data[3] = ( + data[2] = ( + data[1] = ( + data[0] = src[0] ) != 0 ? + src[1] : 0) != 0 ? + src[2] : 0) != 0 ? + src[3] : 0; + return *this; + } + }; + + + /// + /// Blank language ID + /// + const langid_t langid_t_blank = {}; + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a == \p b + /// - false otherwise + /// + inline bool operator==(const langid_t &a, const langid_t & b) + { + return + a.data[0] == b.data[0] && + (a.data[0] == 0 || (a.data[1] == b.data[1] && + (a.data[1] == 0 || (a.data[2] == b.data[2] && + (a.data[2] == 0 || a.data[3] == b.data[3]))))); + } + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a != \p b + /// - false otherwise + /// + inline bool operator!=(const langid_t &a, const langid_t & b) + { + return !operator==(a, b); + } + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a < \p b + /// - false otherwise + /// + inline bool operator<(const langid_t& a, const langid_t& b) + { + if (a.data[0] < b.data[0]) return true; + else if (a.data[0] > b.data[0]) return false; + else if (a.data[1] < b.data[1]) return true; + else if (a.data[1] > b.data[1]) return false; + else if (a.data[2] < b.data[2]) return true; + else if (a.data[2] > b.data[2]) return false; + else if (a.data[3] < b.data[3]) return true; + else return false; + } + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a > \p b + /// - false otherwise + /// + inline bool operator>(const langid_t& a, const langid_t& b) + { + return operator<(b, a); + } + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a <= \p b + /// - false otherwise + /// + inline bool operator<=(const langid_t &a, const langid_t & b) + { + return !operator>(a, b); + } + + + /// + /// Compares two language IDs + /// + /// \param[in] a First language ID + /// \param[in] b Second language ID + /// + /// \returns + /// - true when \p a >= \p b + /// - false otherwise + /// + inline bool operator>=(const langid_t &a, const langid_t & b) + { + return !operator<(a, b); + } #ifdef _WIN32 diff --git a/lib/libZRCola/include/zrcola/language.h b/lib/libZRCola/include/zrcola/language.h index e5e5fec..fa67f5a 100644 --- a/lib/libZRCola/include/zrcola/language.h +++ b/lib/libZRCola/include/zrcola/language.h @@ -98,8 +98,8 @@ namespace ZRCola { if (a.chr < b.chr) return -1; else if (a.chr > b.chr) return 1; - int r = memcmp(a.lang, b.lang, sizeof(langid_t)); - if (r != 0) return r; + if (a.lang < b.lang) return -1; + else if (a.lang > b.lang) return 1; return 0; } @@ -234,8 +234,8 @@ namespace ZRCola { /// virtual int compare(_In_ const language &a, _In_ const language &b) const { - int r = memcmp(a.id, b.id, sizeof(langid_t)); - if (r != 0) return r; + if (a.id < b.id) return -1; + else if (a.id > b.id) return 1; return 0; } diff --git a/lib/libZRCola/include/zrcola/translate.h b/lib/libZRCola/include/zrcola/translate.h index a2d6c76..381b82f 100644 --- a/lib/libZRCola/include/zrcola/translate.h +++ b/lib/libZRCola/include/zrcola/translate.h @@ -224,7 +224,7 @@ namespace ZRCola { /// inline void Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector* map = NULL) const { - Decompose(input, inputMax, NULL, ZRCOLA_LANG_VOID, output, map); + Decompose(input, inputMax, NULL, langid_t_blank, output, map); } /// diff --git a/lib/libZRCola/src/language.cpp b/lib/libZRCola/src/language.cpp index f348661..c5fda39 100644 --- a/lib/libZRCola/src/language.cpp +++ b/lib/libZRCola/src/language.cpp @@ -24,46 +24,46 @@ void ZRCola::LangConvert(_In_ LANGID lang_win, _Inout_ ZRCola::langid_t &lang) { switch (PRIMARYLANGID(lang_win)) { - case LANG_BELARUSIAN : memcpy(lang, "bel", sizeof(lang)); break; - case LANG_CZECH : memcpy(lang, "cze", sizeof(lang)); break; - case LANG_DANISH : memcpy(lang, "dan", sizeof(lang)); break; - case LANG_GERMAN : memcpy(lang, "deu", sizeof(lang)); break; - case LANG_ENGLISH : memcpy(lang, "eng", sizeof(lang)); break; - case LANG_ESTONIAN : memcpy(lang, "est", sizeof(lang)); break; - case LANG_FRENCH : memcpy(lang, "fra", sizeof(lang)); break; - case LANG_IRISH : memcpy(lang, "gle", sizeof(lang)); break; - case LANG_HUNGARIAN : memcpy(lang, "hun", sizeof(lang)); break; - case LANG_LATVIAN : memcpy(lang, "lav", sizeof(lang)); break; - case LANG_LITHUANIAN : memcpy(lang, "lit", sizeof(lang)); break; - case LANG_MACEDONIAN : memcpy(lang, "mkd", sizeof(lang)); break; - case LANG_MALTESE : memcpy(lang, "mlt", sizeof(lang)); break; - case LANG_NORWEGIAN : memcpy(lang, "nor", sizeof(lang)); break; - case LANG_POLISH : memcpy(lang, "pol", sizeof(lang)); break; - case LANG_PORTUGUESE : memcpy(lang, "por", sizeof(lang)); break; - case LANG_ROMANIAN : memcpy(lang, "rum", sizeof(lang)); break; - case LANG_RUSSIAN : memcpy(lang, "rus", sizeof(lang)); break; - case LANG_SLOVAK : memcpy(lang, "slk", sizeof(lang)); break; - case LANG_SLOVENIAN : memcpy(lang, "slv", sizeof(lang)); break; - case LANG_SPANISH : memcpy(lang, "spa", sizeof(lang)); break; - case LANG_ALBANIAN : memcpy(lang, "sqi", sizeof(lang)); break; - case LANG_SWEDISH : memcpy(lang, "swe", sizeof(lang)); break; - case LANG_TURKISH : memcpy(lang, "tur", sizeof(lang)); break; - case LANG_UKRAINIAN : memcpy(lang, "ukr", sizeof(lang)); break; + case LANG_BELARUSIAN : lang = "bel"; break; + case LANG_CZECH : lang = "cze"; break; + case LANG_DANISH : lang = "dan"; break; + case LANG_GERMAN : lang = "deu"; break; + case LANG_ENGLISH : lang = "eng"; break; + case LANG_ESTONIAN : lang = "est"; break; + case LANG_FRENCH : lang = "fra"; break; + case LANG_IRISH : lang = "gle"; break; + case LANG_HUNGARIAN : lang = "hun"; break; + case LANG_LATVIAN : lang = "lav"; break; + case LANG_LITHUANIAN : lang = "lit"; break; + case LANG_MACEDONIAN : lang = "mkd"; break; + case LANG_MALTESE : lang = "mlt"; break; + case LANG_NORWEGIAN : lang = "nor"; break; + case LANG_POLISH : lang = "pol"; break; + case LANG_PORTUGUESE : lang = "por"; break; + case LANG_ROMANIAN : lang = "rum"; break; + case LANG_RUSSIAN : lang = "rus"; break; + case LANG_SLOVAK : lang = "slk"; break; + case LANG_SLOVENIAN : lang = "slv"; break; + case LANG_SPANISH : lang = "spa"; break; + case LANG_ALBANIAN : lang = "sqi"; break; + case LANG_SWEDISH : lang = "swe"; break; + case LANG_TURKISH : lang = "tur"; break; + case LANG_UKRAINIAN : lang = "ukr"; break; case LANG_CROATIAN : // LANG_BOSNIAN, and LANG_SERBIAN switch (SUBLANGID(lang_win)) { - case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN : memcpy(lang, "bos", sizeof(lang)); break; - case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC : memcpy(lang, "boz", sizeof(lang)); break; + case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN : lang = "bos"; break; + case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC : lang = "boz"; break; case SUBLANG_CROATIAN_CROATIA : - case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN : memcpy(lang, "hrv", sizeof(lang)); break; + case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN : lang = "hrv"; break; case SUBLANG_SERBIAN_LATIN : case SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN : case SUBLANG_SERBIAN_MONTENEGRO_LATIN : - case SUBLANG_SERBIAN_SERBIA_LATIN : memcpy(lang, "srp", sizeof(lang)); break; + case SUBLANG_SERBIAN_SERBIA_LATIN : lang = "srp"; break; case SUBLANG_SERBIAN_CYRILLIC : case SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC : case SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC : - case SUBLANG_SERBIAN_SERBIA_CYRILLIC : memcpy(lang, "srz", sizeof(lang)); break; + case SUBLANG_SERBIAN_SERBIA_CYRILLIC : lang = "srz"; break; } break; } @@ -83,9 +83,8 @@ bool ZRCola::langchar_db::IsLocalCharacter(_In_ wchar_t chr, _In_ ZRCola::langid else if (lc.chr < chr ) l = m + 1; else { // Do the bisection test on language. - int res = memcmp(lang, lc.lang, sizeof(langid_t)); - if (res < 0) r = m; - else if (res > 0) l = m + 1; + if (lang < lc.lang) r = m; + else if (lang > lc.lang) l = m + 1; else { // Match found. return true;