Languages and language-specific characters added to the database

This commit is contained in:
2016-04-11 12:41:22 +02:00
parent fc93474b9a
commit 177edd19e8
10 changed files with 848 additions and 2 deletions

View File

@@ -127,6 +127,21 @@ bool ZRCola::DBSource::GetValue(const ATL::CComPtr<ADOField>& f, int& val) const
}
bool ZRCola::DBSource::GetValue(const ATL::CComPtr<ADOField>& f, std::wstring& val) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
val.reserve(::SysStringLen(V_BSTR(&v)));
val = V_BSTR(&v);
return true;
}
bool ZRCola::DBSource::GetUnicodeCharacter(const ATL::CComPtr<ADOField>& f, wchar_t& chr) const
{
wxASSERT_MSG(f, wxT("field is empty"));
@@ -241,6 +256,45 @@ bool ZRCola::DBSource::GetKeyCode(const ATL::CComPtr<ADOField>& f, ZRCola::DBSou
}
bool ZRCola::DBSource::GetLanguage(const ATL::CComPtr<ADOField>& f, ZRCola::langid_t& lang) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
// Convert to lowercase.
_wcslwr_l(V_BSTR(&v), m_locale);
// Parse the field.
size_t n = wcsnlen(V_BSTR(&v), ::SysStringLen(V_BSTR(&v)));
if (n != 3) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0080: Syntax error in \"%.*ls\" field (\"%.*ls\"). Language ID must be exactly three (3) characters long.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
return false;
}
for (size_t i = 0;; i++) {
if (i < sizeof(lang)) {
if (i < n) {
wchar_t c = V_BSTR(&v)[i];
if ((unsigned short)c > 0x7f) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_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;
} else
lang[i] = 0;
} else
break;
}
return true;
}
bool ZRCola::DBSource::SelectTranslations(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
@@ -347,3 +401,77 @@ bool ZRCola::DBSource::GetKeySequence(const ATL::CComPtr<ADORecordset>& rs, ZRCo
return true;
}
bool ZRCola::DBSource::SelectLanguages(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
if (rs) rs.Release();
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(L"SELECT DISTINCT [entCode] FROM [VRS_Jezik]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText))) {
_ftprintf(stderr, wxT("%s: error ZCC0060: Error loading languages from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
}
return true;
}
bool ZRCola::DBSource::GetLanguage(const ATL::CComPtr<ADORecordset>& rs, ZRCola::DBSource::language& lang) const
{
wxASSERT_MSG(rs, wxT("recordset is empty"));
ATL::CComPtr<ADOFields> flds;
wxVERIFY(SUCCEEDED(rs->get_Fields(&flds)));
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"entCode"), &f)));
wxCHECK(GetLanguage(f, lang.id), false);
}
return true;
}
bool ZRCola::DBSource::SelectLanguageCharacters(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
if (rs) rs.Release();
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(L"SELECT DISTINCT [znak], [lang] FROM [VRS_CharLocal]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText))) {
_ftprintf(stderr, wxT("%s: error ZCC0090: Error loading language characters from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
}
return true;
}
bool ZRCola::DBSource::GetLanguageCharacter(const ATL::CComPtr<ADORecordset>& rs, ZRCola::DBSource::langchar& lc) const
{
wxASSERT_MSG(rs, wxT("recordset is empty"));
ATL::CComPtr<ADOFields> flds;
wxVERIFY(SUCCEEDED(rs->get_Fields(&flds)));
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"znak"), &f)));
wxCHECK(GetUnicodeCharacter(f, lc.chr), false);
}
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"lang"), &f)));
wxCHECK(GetLanguage(f, lc.lang), false);
}
return true;
}

View File

@@ -19,6 +19,8 @@
#pragma once
#include <zrcola/language.h>
#include <atlbase.h>
#include <adoint.h>
#include <string>
@@ -62,6 +64,25 @@ namespace ZRCola {
std::vector<keycode> seq; ///< Key sequence
};
///
/// Language
///
class language {
public:
ZRCola::langid_t id; ///< Language ID
};
///
/// Language Character
///
class langchar {
public:
wchar_t chr; ///> Character
ZRCola::langid_t lang; ///< Language ID
};
public:
DBSource();
virtual ~DBSource();
@@ -141,6 +162,19 @@ namespace ZRCola {
bool GetValue(const ATL::CComPtr<ADOField>& f, int& val) const;
///
/// Gets string from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] val Output string value
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetValue(const ATL::CComPtr<ADOField>& f, std::wstring& val) const;
///
/// Gets encoded Unicode character from ZRCola.zrc database
///
@@ -180,6 +214,19 @@ namespace ZRCola {
bool GetKeyCode(const ATL::CComPtr<ADOField>& f, keyseq::keycode& kc) const;
///
/// Gets language ID from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] lang Language
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetLanguage(const ATL::CComPtr<ADOField>& f, langid_t& lang) const;
///
/// Returns character translations
///
@@ -229,6 +276,56 @@ namespace ZRCola {
///
bool GetKeySequence(const ATL::CComPtr<ADORecordset>& rs, keyseq& ks) const;
///
/// Returns languages
///
/// \param[out] rs Recordset with results
///
/// \returns
/// - true when query succeeds
/// - false otherwise
///
bool SelectLanguages(ATL::CComPtr<ADORecordset>& rs) const;
///
/// Returns language data
///
/// \param[in] rs Recordset with results
/// \param[out] lang Language
///
/// \returns
/// - true when succeeded
/// - false otherwise
///
bool GetLanguage(const ATL::CComPtr<ADORecordset>& rs, language& lang) const;
///
/// Returns language character
///
/// \param[out] rs Recordset with results
///
/// \returns
/// - true when query succeeds
/// - false otherwise
///
bool SelectLanguageCharacters(ATL::CComPtr<ADORecordset>& rs) const;
///
/// Returns language character data
///
/// \param[in] rs Recordset with results
/// \param[out] lang Language character data
///
/// \returns
/// - true when succeeded
/// - false otherwise
///
bool GetLanguageCharacter(const ATL::CComPtr<ADORecordset>& rs, langchar& lc) const;
protected:
std::basic_string<TCHAR> m_filename; ///< Database filename
ATL::CComPtr<ADOConnection> m_db; ///< Database

View File

@@ -132,6 +132,117 @@ inline std::ostream& operator <<(std::ostream& stream, const ZRCola::keyseq_db &
}
///
/// Writes language database to a stream
///
/// \param[in] stream Output stream
/// \param[in] db Language database
///
/// \returns The stream \p stream
///
inline std::ostream& operator <<(std::ostream& stream, const ZRCola::language_db &db)
{
unsigned __int32 count;
// Write index count.
ZRCola::language_db::indexLang::size_type lang_count = db.idxLng.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (lang_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)lang_count;
stream.write((const char*)&count, sizeof(count));
// Write language index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
// Write data count.
std::vector<unsigned __int16>::size_type data_count = db.data.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (data_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)data_count;
stream.write((const char*)&count, sizeof(count));
// Write data.
if (stream.fail()) return stream;
stream.write((const char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
///
/// Writes language character database to a stream
///
/// \param[in] stream Output stream
/// \param[in] db Language character database
///
/// \returns The stream \p stream
///
inline std::ostream& operator <<(std::ostream& stream, const ZRCola::langchar_db &db)
{
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
assert(db.idxChr.size() == db.idxLng.size());
#endif
unsigned __int32 count;
// Write index count.
ZRCola::langchar_db::indexChar::size_type lc_count = db.idxChr.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (lc_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)lc_count;
stream.write((const char*)&count, sizeof(count));
// Write character index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxChr.data(), sizeof(unsigned __int32)*count);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
// Write language index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
#endif
// Write data count.
std::vector<unsigned __int16>::size_type data_count = db.data.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (data_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)data_count;
stream.write((const char*)&count, sizeof(count));
// Write data.
if (stream.fail()) return stream;
stream.write((const char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
///
/// Main function
///
@@ -259,7 +370,6 @@ int _tmain(int argc, _TCHAR *argv[])
}
}
{
// Get key sequences.
ATL::CComPtr<ADORecordset> rs;
@@ -329,6 +439,102 @@ int _tmain(int argc, _TCHAR *argv[])
}
}
{
// Get languages.
ATL::CComPtr<ADORecordset> rs;
if (src.SelectLanguages(rs)) {
size_t count = src.GetRecordsetCount(rs);
if (count < 0xffffffff) { // 4G check (-1 is reserved for error condition)
ZRCola::DBSource::language lang;
ZRCola::language_db db;
// Preallocate memory.
db.idxLng.reserve(count);
db.data .reserve(count*4);
// Parse languages and build index and data.
while (!ZRCola::DBSource::IsEOF(rs)) {
// Read language from the database.
if (src.GetLanguage(rs, lang)) {
// 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.idxLng.push_back(idx);
} else
has_errors = true;
wxVERIFY(SUCCEEDED(rs->MoveNext()));
}
// Sort indices.
db.idxLng.sort();
// Write languages to file.
dst << ZRCola::language_rec(db);
} else {
_ftprintf(stderr, wxT("%s: error ZCC0009: Error getting language count from database or too many languages.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
} else {
_ftprintf(stderr, wxT("%s: error ZCC0008: Error getting languages from database. Please make sure the file is ZRCola.zrc compatible.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
}
{
// Get language characters.
ATL::CComPtr<ADORecordset> rs;
if (src.SelectLanguageCharacters(rs)) {
size_t count = src.GetRecordsetCount(rs);
if (count < 0xffffffff) { // 4G check (-1 is reserved for error condition)
ZRCola::DBSource::langchar lc;
ZRCola::langchar_db db;
// Preallocate memory.
db.idxChr.reserve(count);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.reserve(count);
#endif
db.data .reserve(count*4);
// Parse language characters and build index and data.
while (!ZRCola::DBSource::IsEOF(rs)) {
// Read language characters from the database.
if (src.GetLanguageCharacter(rs, lc)) {
// Add language characters to index and data.
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.idxChr.push_back(idx);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.push_back(idx);
#endif
} else
has_errors = true;
wxVERIFY(SUCCEEDED(rs->MoveNext()));
}
// Sort indices.
db.idxChr .sort();
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.sort();
#endif
// Write language characters to file.
dst << ZRCola::langchar_rec(db);
} else {
_ftprintf(stderr, wxT("%s: error ZCC0011: Error getting language characters count from database or too many langchars.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
} else {
_ftprintf(stderr, wxT("%s: error ZCC0010: Error getting language characters from database. Please make sure the file is ZRCola.zrc compatible.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
}
stdex::idrec::close<ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>(dst, dst_start);
if (dst.fail()) {

View File

@@ -24,6 +24,7 @@
#include "../include/zrcola.h"
#include "dbsource.h"
#include <zrcola/language.h>
#include <zrcola/translate.h>
#include <zrcolaui/keyboard.h>