moved winix directories to winixdsubdirectory
git-svn-id: svn://ttmath.org/publicrep/winix/trunk@1028 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
875
winixd/templates/locale.cpp
Normal file
875
winixd/templates/locale.cpp
Normal file
@@ -0,0 +1,875 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2014, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "locale.h"
|
||||
#include "core/log.h"
|
||||
#include "core/misc.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
namespace Winix
|
||||
{
|
||||
|
||||
|
||||
Locale::Locale()
|
||||
{
|
||||
default_lang = 0;
|
||||
current_lang = 0;
|
||||
}
|
||||
|
||||
|
||||
void Locale::SetLocaleFiles(const std::vector<std::wstring> & files)
|
||||
{
|
||||
locale_files = files;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Locale::SetLocaleMaxId(size_t max_id)
|
||||
{
|
||||
if( max_id > 1000 )
|
||||
{
|
||||
max_id = 1000;
|
||||
log << log1 << "Locale: locale_max_id is too big (changed to 1000)" << logend;
|
||||
}
|
||||
|
||||
size_t old_size = locale_indices.size();
|
||||
locale_indices.resize(max_id + 1);
|
||||
|
||||
for(size_t i=old_size ; i<locale_indices.size() ; ++i)
|
||||
locale_indices[i] = size_t(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Locale::HasLanguage(size_t lang_id)
|
||||
{
|
||||
if( lang_id < locale_indices.size() )
|
||||
return locale_indices[lang_id] < locale_tab.size();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Locale::ReadFile(const char * dir, const char * dir_def, const char * file)
|
||||
{
|
||||
bool read = false;
|
||||
temp_space.Clear();
|
||||
|
||||
if( dir_def && ReadFile(dir_def, file) )
|
||||
read = true;
|
||||
|
||||
if( dir && ReadFile(dir, file) )
|
||||
read = true;
|
||||
|
||||
if( read )
|
||||
AddLocale(file);
|
||||
else
|
||||
log << log1 << "Locale: can't open locale's file: " << file << logend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Locale::ReadFile(const char * dir, const char * file)
|
||||
{
|
||||
bool read = false;
|
||||
|
||||
file_name = dir;
|
||||
file_name += '/';
|
||||
file_name += file;
|
||||
|
||||
loc_parser.SplitSingle(true);
|
||||
loc_parser.SetSpace(temp_space);
|
||||
|
||||
PT::SpaceParser::Status status = loc_parser.Parse(file_name);
|
||||
|
||||
if( status == PT::SpaceParser::ok )
|
||||
{
|
||||
read = true;
|
||||
log << log3 << "Locale: read locale from: " << file_name << logend;
|
||||
}
|
||||
else
|
||||
if( status == PT::SpaceParser::syntax_error )
|
||||
{
|
||||
log << log1 << "Locale: syntax error in: " << file_name << " in line: " << loc_parser.line << logend;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Locale::AddLocale(const char * file)
|
||||
{
|
||||
std::wstring * id_str = temp_space.GetValue(L"winix_locale_id");
|
||||
|
||||
if( !id_str )
|
||||
{
|
||||
log << log1 << "Locale: winix_locale_id field should be defined in locale file: "
|
||||
<< file << " (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t id = (size_t)Tol(*id_str);
|
||||
|
||||
if( id >= locale_indices.size() )
|
||||
{
|
||||
log << log1 << "Locale: locale identifier is greater than locale_max_id (skipping)" << logend;
|
||||
return;
|
||||
}
|
||||
|
||||
locale_tab.push_back(temp_space);
|
||||
locale_indices[id] = locale_tab.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Locale::ReadSubstTable(const char * dir, const char * dir_def)
|
||||
{
|
||||
bool read = false;
|
||||
|
||||
subst_url.clear();
|
||||
subst_smalllet.clear();
|
||||
subst_capitallet.clear();
|
||||
subst_sort.clear();
|
||||
|
||||
if( dir_def && ReadSubstTable(dir_def) )
|
||||
read = true;
|
||||
|
||||
if( dir && ReadSubstTable(dir) )
|
||||
read = true;
|
||||
|
||||
if( !read )
|
||||
log << log1 << "Locale: can't open file for characters substitution" << logend;
|
||||
}
|
||||
|
||||
|
||||
bool Locale::ReadSubstTable(const char * dir)
|
||||
{
|
||||
bool read = false;
|
||||
|
||||
file_name = dir;
|
||||
file_name += '/';
|
||||
file_name += "substitute";
|
||||
|
||||
loc_parser.SplitSingle(true);
|
||||
loc_parser.SetSpace(temp_space);
|
||||
|
||||
if( loc_parser.Parse(file_name) == PT::SpaceParser::ok )
|
||||
{
|
||||
read = true;
|
||||
CreateSubstVector(subst_url, temp_space.table_single[L"url_original"], temp_space.table_single[L"url_changeto"]);
|
||||
CreateSubstVector(subst_smalllet, temp_space.table_single[L"smallleters"], temp_space.table_single[L"capitalics"]);
|
||||
CreateSubstVector(subst_capitallet, temp_space.table_single[L"capitalics"], temp_space.table_single[L"smallleters"]);
|
||||
CreateSubstSortVector(subst_sort, temp_space.table[L"sort"]);
|
||||
|
||||
log << log3 << "Locale: read characters substitution tables from: " << file_name << logend;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
void Locale::CreateSubstVector(std::vector<SubstItem> & vect, const std::wstring & tab1, const std::wstring & tab2)
|
||||
{
|
||||
size_t i, min_size = (tab1.size() < tab2.size()) ? tab1.size() : tab2.size();
|
||||
SubstItem s;
|
||||
|
||||
vect.clear();
|
||||
|
||||
if( min_size == 0 )
|
||||
return;
|
||||
|
||||
vect.reserve(min_size);
|
||||
|
||||
for(i=0 ; i<min_size ; ++i)
|
||||
{
|
||||
s.from = tab1[i];
|
||||
s.to = tab2[i];
|
||||
vect.push_back(s);
|
||||
}
|
||||
|
||||
std::sort(vect.begin(), vect.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Locale::CreateSubstSortVector(std::vector<SubstItem> & vect, std::vector<std::wstring> & tab)
|
||||
{
|
||||
SubstItem s;
|
||||
|
||||
vect.clear();
|
||||
|
||||
if( tab.empty() )
|
||||
return;
|
||||
|
||||
vect.reserve(tab.size());
|
||||
|
||||
for(size_t i=0 ; i<tab.size() ; ++i)
|
||||
{
|
||||
if( tab[i].size() >= 3 )
|
||||
{
|
||||
s.from = tab[i][0];
|
||||
s.to = tab[i][1];
|
||||
s.index = Toi(&tab[i][2]);
|
||||
|
||||
vect.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(vect.begin(), vect.end());
|
||||
}
|
||||
|
||||
|
||||
void Locale::Read(const char * dir, const char * dir_def)
|
||||
{
|
||||
locale_tab.clear();
|
||||
|
||||
for(size_t i=0 ; i<locale_indices.size() ; ++i)
|
||||
locale_indices[i] = size_t(-1);
|
||||
|
||||
for(size_t i=0 ; i<locale_files.size() ; ++i)
|
||||
{
|
||||
PT::WideToUTF8(locale_files[i], locale_filea);
|
||||
ReadFile(dir, dir_def, locale_filea.c_str());
|
||||
}
|
||||
|
||||
ReadSubstTable(dir, dir_def);
|
||||
}
|
||||
|
||||
|
||||
void Locale::Read(const std::string & dir, const std::string & dir_def)
|
||||
{
|
||||
if( dir_def.empty() )
|
||||
Read(dir.c_str());
|
||||
else
|
||||
Read(dir.c_str(), dir_def.c_str());
|
||||
}
|
||||
|
||||
|
||||
void Locale::Read(const wchar_t * dir, const wchar_t * dir_def)
|
||||
{
|
||||
PT::WideToUTF8(dir, adir1);
|
||||
|
||||
if( !dir_def )
|
||||
{
|
||||
Read(adir1.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
PT::WideToUTF8(dir_def, adir2);
|
||||
Read(adir1.c_str(), adir2.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Locale::Read(const std::wstring & dir, const std::wstring & dir_def)
|
||||
{
|
||||
if( dir_def.empty() )
|
||||
Read(dir.c_str());
|
||||
else
|
||||
Read(dir.c_str(), dir_def.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Locale::SetCurLang(size_t lang_id)
|
||||
{
|
||||
current_lang = lang_id;
|
||||
}
|
||||
|
||||
|
||||
size_t Locale::GetCurLang() const
|
||||
{
|
||||
return current_lang;
|
||||
}
|
||||
|
||||
|
||||
void Locale::SetDefLang(size_t lang_id)
|
||||
{
|
||||
default_lang = lang_id;
|
||||
}
|
||||
|
||||
|
||||
size_t Locale::GetDefLang() const
|
||||
{
|
||||
return default_lang;
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsKey(const wchar_t * key, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsKey(key_str, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsKey(const std::wstring & key, bool try_default_too) const
|
||||
{
|
||||
return IsKey(key, current_lang, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsKey(const wchar_t * key, size_t lang_id, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsKey(key_str, lang_id, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::wstring * Locale::GetKeyInLanguage(const std::wstring & key, size_t lang_id) const
|
||||
{
|
||||
if( lang_id < locale_indices.size() )
|
||||
{
|
||||
size_t index = locale_indices[lang_id];
|
||||
|
||||
if( index < locale_tab.size() )
|
||||
return locale_tab[index].GetValue(key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsKey(const std::wstring & key, size_t lang_id, bool try_default_too) const
|
||||
{
|
||||
if( GetKeyInLanguage(key, lang_id) != 0 )
|
||||
return true;
|
||||
|
||||
if( !try_default_too || lang_id == default_lang )
|
||||
return false;
|
||||
|
||||
return GetKeyInLanguage(key, default_lang) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const std::wstring & Locale::Get(const wchar_t * key, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return Get(key_str, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::wstring & Locale::Get(const std::wstring & key, bool try_default_too) const
|
||||
{
|
||||
return Get(key, current_lang, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::wstring & Locale::Get(const wchar_t * key, size_t lang_id, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return Get(key_str, lang_id, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::wstring & Locale::Get(const std::wstring & key, size_t lang_id, bool try_default_too) const
|
||||
{
|
||||
const std::wstring * value = GetKeyInLanguage(key, lang_id);
|
||||
|
||||
if( value )
|
||||
return *value;
|
||||
|
||||
if( !try_default_too || lang_id == default_lang )
|
||||
return empty;
|
||||
|
||||
value = GetKeyInLanguage(key, default_lang);
|
||||
|
||||
if( value )
|
||||
return *value;
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Locale::IsList(const wchar_t * key, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsList(key_str, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsList(const std::wstring & key, bool try_default_too) const
|
||||
{
|
||||
return IsList(key, current_lang, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Locale::IsList(const wchar_t * key, size_t lang_id, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsList(key_str, lang_id, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Locale::IsList(const std::wstring & key, size_t lang_id, bool try_default_too) const
|
||||
{
|
||||
if( GetListInLanguage(key, lang_id) != 0 )
|
||||
return true;
|
||||
|
||||
if( !try_default_too || lang_id == default_lang )
|
||||
return false;
|
||||
|
||||
return GetListInLanguage(key, default_lang) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetList(const wchar_t * key, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return GetList(key_str, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetList(const std::wstring & key, bool try_default_too) const
|
||||
{
|
||||
return GetList(key, current_lang, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetList(const wchar_t * key, size_t lang_id, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return GetList(key_str, lang_id, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::vector<std::wstring> * Locale::GetListInLanguage(const std::wstring & key, size_t lang_id) const
|
||||
{
|
||||
if( lang_id < locale_indices.size() )
|
||||
{
|
||||
size_t index = locale_indices[lang_id];
|
||||
|
||||
if( index < locale_tab.size() )
|
||||
{
|
||||
PT::Space::Table::const_iterator i = locale_tab[index].table.find(key);
|
||||
|
||||
if( i != locale_tab[index].table.end() )
|
||||
return &i->second;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetList(const std::wstring & key,
|
||||
size_t lang_id, bool try_default_too) const
|
||||
{
|
||||
const std::vector<std::wstring> * list = GetListInLanguage(key, lang_id);
|
||||
|
||||
if( list )
|
||||
return *list;
|
||||
|
||||
if( !try_default_too || lang_id == default_lang )
|
||||
return empty_list;
|
||||
|
||||
list = GetListInLanguage(key, default_lang);
|
||||
|
||||
if( list )
|
||||
return *list;
|
||||
|
||||
return empty_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t Locale::IdToIndex(size_t lang_id)
|
||||
{
|
||||
if( lang_id < locale_indices.size() )
|
||||
return locale_indices[lang_id]; // here can be size(-1) as well
|
||||
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
|
||||
size_t Locale::Size() const
|
||||
{
|
||||
return locale_tab.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Locale::IsKeyByIndex(const wchar_t * key, size_t index, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsKeyByIndex(key_str, index, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsKeyByIndex(const std::wstring & key, size_t index, bool try_default_too) const
|
||||
{
|
||||
if( index < locale_tab.size() )
|
||||
{
|
||||
if( locale_tab[index].GetValue(key) != 0 )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( try_default_too )
|
||||
{
|
||||
if( GetKeyInLanguage(key, default_lang) != 0 )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const std::wstring & Locale::GetByIndex(const wchar_t * key, size_t index, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return GetByIndex(key_str, index, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::wstring & Locale::GetByIndex(const std::wstring & key, size_t index,
|
||||
bool try_default_too) const
|
||||
{
|
||||
if( index < locale_tab.size() )
|
||||
{
|
||||
const std::wstring * value = locale_tab[index].GetValue(key);
|
||||
|
||||
if( value )
|
||||
return *value;
|
||||
}
|
||||
|
||||
if( try_default_too )
|
||||
{
|
||||
const std::wstring * value = GetKeyInLanguage(key, default_lang);
|
||||
|
||||
if( value )
|
||||
return *value;
|
||||
}
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Locale::IsListByIndex(const wchar_t * key, size_t index, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return IsListByIndex(key_str, index, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
bool Locale::IsListByIndex(const std::wstring & key, size_t index, bool try_default_too) const
|
||||
{
|
||||
if( index < locale_tab.size() )
|
||||
{
|
||||
PT::Space::Table::const_iterator i = locale_tab[index].table.find(key);
|
||||
|
||||
if( i != locale_tab[index].table.end() )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( try_default_too )
|
||||
return GetListInLanguage(key, default_lang) != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetListByIndex(const wchar_t * key,
|
||||
size_t index, bool try_default_too)
|
||||
{
|
||||
key_str = key;
|
||||
return GetListByIndex(key_str, index, try_default_too);
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::wstring> & Locale::GetListByIndex(const std::wstring & key,
|
||||
size_t index, bool try_default_too) const
|
||||
{
|
||||
if( index < locale_tab.size() )
|
||||
{
|
||||
PT::Space::Table::const_iterator i = locale_tab[index].table.find(key);
|
||||
|
||||
if( i != locale_tab[index].table.end() )
|
||||
return i->second;
|
||||
}
|
||||
|
||||
if( try_default_too )
|
||||
{
|
||||
const std::vector<std::wstring> * value = GetListInLanguage(key, default_lang);
|
||||
|
||||
if( value )
|
||||
return *value;
|
||||
}
|
||||
|
||||
return empty_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
binary search in vect
|
||||
vect should be sorted by 'from'
|
||||
|
||||
if the 'val' is found in vect[].from then its index is returned (index to vect table)
|
||||
else vect.size() is returned
|
||||
*/
|
||||
size_t Locale::SubstFindIndex(const std::vector<SubstItem> & vect, wchar_t val)
|
||||
{
|
||||
if( vect.empty() )
|
||||
return vect.size();
|
||||
|
||||
size_t o1 = 0;
|
||||
size_t o2 = vect.size() - 1;
|
||||
|
||||
if( val < vect[o1].from )
|
||||
return vect.size();
|
||||
|
||||
if( val == vect[o1].from )
|
||||
return o1;
|
||||
|
||||
if( val > vect[o2].from )
|
||||
return vect.size();
|
||||
|
||||
if( val == vect[o2].from )
|
||||
return o2;
|
||||
|
||||
while( o1 + 1 < o2 )
|
||||
{
|
||||
size_t o = (o1 + o2) / 2;
|
||||
|
||||
if( val == vect[o].from )
|
||||
return o;
|
||||
|
||||
if( val < vect[o].from )
|
||||
o2 = o;
|
||||
else
|
||||
o1 = o;
|
||||
}
|
||||
|
||||
return vect.size();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
binary search in vect
|
||||
vect should be sorted by 'from'
|
||||
|
||||
if the 'val' is found in vect[].from then vect[].to is returned
|
||||
else 'val' is returned
|
||||
*/
|
||||
wchar_t Locale::SubstFind(const std::vector<SubstItem> & vect, wchar_t val)
|
||||
{
|
||||
size_t i = SubstFindIndex(vect, val);
|
||||
|
||||
if( i == vect.size() )
|
||||
{
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vect[i].to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wchar_t Locale::UrlSubst(wchar_t c)
|
||||
{
|
||||
return SubstFind(subst_url, c);
|
||||
}
|
||||
|
||||
|
||||
void Locale::UrlSubst(std::wstring & str)
|
||||
{
|
||||
for(size_t i=0 ; i<str.size() ; ++i)
|
||||
str[i] = UrlSubst(str[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wchar_t Locale::ToSmall(wchar_t c)
|
||||
{
|
||||
if( c>='A' && c<='Z' )
|
||||
return c - 'A' + 'a';
|
||||
|
||||
return SubstFind(subst_capitallet, c);
|
||||
}
|
||||
|
||||
|
||||
void Locale::ToSmall(std::wstring & str)
|
||||
{
|
||||
for(size_t i=0 ; i<str.size() ; ++i)
|
||||
str[i] = ToSmall(str[i]);
|
||||
}
|
||||
|
||||
|
||||
wchar_t Locale::ToCapital(wchar_t c)
|
||||
{
|
||||
if( c>='a' && c<='z' )
|
||||
return c - 'a' + 'A';
|
||||
|
||||
return SubstFind(subst_smalllet, c);
|
||||
}
|
||||
|
||||
|
||||
void Locale::ToCapital(std::wstring & str)
|
||||
{
|
||||
for(size_t i=0 ; i<str.size() ; ++i)
|
||||
str[i] = ToCapital(str[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
comparing lexicographically two characters
|
||||
|
||||
return value:
|
||||
less than 0 if c1 is 'less' than c2
|
||||
zero if they are equal
|
||||
greater than 0 if c1 is 'greater' than c2
|
||||
|
||||
capital letters are treated equaly as small ones
|
||||
but they will appear first (before the small ones)
|
||||
*/
|
||||
int Locale::Compare(wchar_t c1, wchar_t c2)
|
||||
{
|
||||
SubstItem s1, s2;
|
||||
|
||||
s1.from = c1;
|
||||
s1.to = c1;
|
||||
s1.index = 0;
|
||||
|
||||
s2.from = c2;
|
||||
s2.to = c2;
|
||||
s2.index = 0;
|
||||
|
||||
if( !((c1>='a' && c1<='z') || (c1>='A' && c1<='Z')) )
|
||||
{
|
||||
size_t i1 = SubstFindIndex(subst_sort, c1);
|
||||
|
||||
if( i1 < subst_sort.size() )
|
||||
{
|
||||
s1.to = subst_sort[i1].to;
|
||||
s1.index = subst_sort[i1].index;
|
||||
}
|
||||
}
|
||||
|
||||
if( !((c2>='a' && c2<='z') || (c2>='A' && c2<='Z')) )
|
||||
{
|
||||
size_t i2 = SubstFindIndex(subst_sort, c2);
|
||||
|
||||
if( i2 < subst_sort.size() )
|
||||
{
|
||||
s2.to = subst_sort[i2].to;
|
||||
s2.index = subst_sort[i2].index;
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t small1 = ToSmall(s1.to);
|
||||
wchar_t small2 = ToSmall(s2.to);
|
||||
|
||||
if( small1 == small2 )
|
||||
{
|
||||
if( s1.index != s2.index )
|
||||
return s1.index - s2.index;
|
||||
|
||||
// this will sort capital letters at the end (after small ones)
|
||||
return s1.to - s2.to;
|
||||
}
|
||||
|
||||
return small1 - small2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
comparing lexicographically two strings
|
||||
|
||||
return value:
|
||||
less than 0 if str1 is 'less' than str2
|
||||
zero if they are equal
|
||||
greater than 0 if str1 is 'greater' than str2
|
||||
*/
|
||||
int Locale::Compare(const std::wstring & str1, const std::wstring & str2)
|
||||
{
|
||||
size_t i1 = 0;
|
||||
size_t i2 = 0;
|
||||
|
||||
for( ; i1 < str1.size() && i2 < str2.size() ; ++i1, ++i2)
|
||||
{
|
||||
int res = Compare(str1[i1], str2[i2]);
|
||||
|
||||
if( res != 0 )
|
||||
return res;
|
||||
}
|
||||
|
||||
if( str1.size() < str2.size() )
|
||||
return -1;
|
||||
|
||||
if( str1.size() > str2.size() )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Winix
|
||||
|
||||
Reference in New Issue
Block a user