Winix framework is a complete infrastructure written in the C++ programming language to create modern web applications and APIs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

296 lines
11 KiB

/*
* 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-2018, 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.
*
*/
#ifndef headerfile_winix_templates_locale
#define headerfile_winix_templates_locale
#include <vector>
#include <string>
#include "space/spaceparser.h"
#include "textstream/textstream.h"
#include "core/winixbase.h"
#include "convert/patternreplacer.h"
namespace Winix
{
class Locale : public WinixBase
{
public:
Locale();
// locale files
// those files will be reading from directories specified in Read() method
// default one item: en
void SetLocaleFiles(const std::vector<std::wstring> & files);
// preparing locale_indices table
// if you change this values you should reload all locale files
void SetLocaleMaxId(size_t max_id);
// setting/getting current language
// default: 0
void SetCurLang(size_t lang_id);
size_t GetCurLang() const;
// which language is used instead of if there is no a key in an other language
// default: 0
void SetDefLang(size_t lang_id);
size_t GetDefLang() const;
// reading locales
// you should call SetLocaleFiles() beforehand
void Read(const char * dir, const char * dir_def = 0);
void Read(const std::string & dir, const std::string & dir_def);
void Read(const wchar_t * dir, const wchar_t * dir_def = 0);
void Read(const std::wstring & dir, const std::wstring & dir_def);
// returns true if a language with lang_id exists
bool HasLanguage(size_t lang_id);
// checking whether there is a 'key' in the current language
// or in the default language if try_default_too is true
bool IsKey(const wchar_t * key, bool try_default_too = true);
bool IsKey(const std::wstring & key, bool try_default_too = true) const;
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool IsKey(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
bool try_default_too = true);
// checking whether there is a 'key' in the lang_id language
// or in the default language if try_default_too is true
bool IsKey(const wchar_t * key, size_t lang_id, bool try_default_too = true);
bool IsKey(const std::wstring & key, size_t lang_id, bool try_default_too = true) const;
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool IsKey(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
size_t lang_id, bool try_default_too = true);
// returning a value for a specific key
const std::wstring & Get(const wchar_t * key, bool try_default_too = true);
const std::wstring & Get(const wchar_t * key, size_t lang_id, bool try_default_too = true);
const std::wstring & Get(const std::wstring & key, bool try_default_too = true) const;
const std::wstring & Get(const std::wstring & key, size_t lang_id, bool try_default_too = true) const;
template<typename char_type, size_t stack_size, size_t heap_block_size>
const std::wstring & Get(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
bool try_default_too = true);
template<typename ... Types>
const std::wstring & GetReplace(const wchar_t * key, Types ... types)
{
const std::wstring & pattern = Get(key, true);
pattern_replacer.ReplaceToString(pattern, pattern_value, types...);
return pattern_value;
}
template<typename ... Types>
const std::wstring & GetReplaceForLang(const wchar_t * key, size_t lang_id, Types ... types)
{
const std::wstring & pattern = Get(key, lang_id, true);
pattern_replacer.ReplaceToString(pattern, pattern_value, types...);
return pattern_value;
}
template<typename ... Types>
const std::wstring & GetReplace(const std::wstring & key, Types ... types) const
{
const std::wstring & pattern = Get(key, true);
pattern_replacer.ReplaceToString(pattern, pattern_value, types...);
return pattern_value;
}
template<typename ... Types>
const std::wstring & GetReplaceForLang(const std::wstring & key, size_t lang_id, Types ... types) const
{
const std::wstring & pattern = Get(key, lang_id, true);
pattern_replacer.ReplaceToString(pattern, pattern_value, types...);
return pattern_value;
}
// lists
bool GetList(const wchar_t * key, std::vector<std::wstring> & list, bool try_default_too = true);
bool GetList(const std::wstring & key, std::vector<std::wstring> & list, bool try_default_too = true) const;
bool GetList(const wchar_t * key, size_t lang_id, std::vector<std::wstring> & list, bool try_default_too = true);
bool GetList(const std::wstring & key, size_t lang_id, std::vector<std::wstring> & list, bool try_default_too = true) const;
// converting lang_id to an internal index
// returns an index from <0, Size()-1> or size_t(-1) if lang_id is incorrect
// it does it in O(1) time
size_t IdToIndex(size_t lang_id);
// returning how many locale files (languages) there are
// this is how many files were correctly parsed
// this is size of locale_tab table
size_t Size() const;
// accessing by an internal index
// internal index is from zero to Size()-1
bool IsKeyByIndex(const wchar_t * key, size_t index, bool try_default_too = true);
bool IsKeyByIndex(const std::wstring & key, size_t index, bool try_default_too = true) const;
const std::wstring & GetByIndex(const wchar_t * key, size_t index, bool try_default_too = true);
const std::wstring & GetByIndex(const std::wstring & key, size_t index, bool try_default_too = true) const;
// lists by an internal index
// current limitation:
// we are looking only in 'space.table' so lists with only one item are not found
// (SplitSingle(true) was called to the space struct)
bool IsListByIndex(const wchar_t * key, size_t index, bool try_default_too = true);
bool IsListByIndex(const std::wstring & key, size_t index, bool try_default_too = true) const;
bool GetListByIndex(const wchar_t * key, size_t index, std::vector<std::wstring> & list, bool try_default_too = true);
bool GetListByIndex(const std::wstring & key, size_t index, std::vector<std::wstring> & list, bool try_default_too = true) const;
// url substitution characters
wchar_t UrlSubst(wchar_t c);
void UrlSubst(std::wstring & str);
// changing to small/capital letters
wchar_t ToSmall(wchar_t c);
void ToSmall(std::wstring & str);
wchar_t ToCapital(wchar_t c);
void ToCapital(std::wstring & str);
// comparing two characters/strings
// return a value less than zero if c1<c2, zero if c1==c2, value greater than 0 if c1>c2
int Compare(wchar_t c1, wchar_t c2);
int Compare(const std::wstring & str1, const std::wstring & str2);
private:
// struct to used for substitution
struct SubstItem
{
wchar_t from, to;
int index;
SubstItem() { from = to = 0; index = 0; }
bool operator<(const SubstItem & arg) const { return from < arg.from; }
};
void AddLocale(const char * file);
void ReadFile(const char * dir, const char * dir_def, const char * file);
bool ReadFile(const char * dir, const char * file);
void ReadSubstTable(const char * dir, const char * dir_def);
bool ReadSubstTable(const char * dir);
void CreateSubstVector(std::vector<SubstItem> & vect, const std::wstring & tab1, const std::wstring & tab2);
void CreateSubstSortVector(std::vector<SubstItem> & vect, std::vector<std::wstring> & tab);
size_t SubstFindIndex(const std::vector<SubstItem> & vect, wchar_t val);
wchar_t SubstFind(const std::vector<SubstItem> & vect, wchar_t val);
const std::wstring * GetKeyInLanguage(const std::wstring & key, size_t lang_id) const;
bool GetListInLanguage(const std::wstring & key, size_t lang_id, std::vector<std::wstring> & list) const;
bool IsListInLanguage(const std::wstring & key, size_t lang_id) const;
// locale files
std::vector<std::wstring> locale_files;
// a map from <0, config->locale_max_id> returning an index to
// locale_tab table (you should check whether the index is correct)
// with this we have O(1) time to find the specified locale
// and locale_tab doesn't have to be so large
std::vector<size_t> locale_indices;
// messages vector<via language>
std::vector<pt::Space> locale_tab;
// default locale index (index to locale_indexes)
size_t default_lang;
// current locale index (index to locale_indexes)
size_t current_lang;
pt::WPatternReplacer pattern_replacer;
// vectors of characters substitution (sort by 'from')
std::vector<SubstItem> subst_url; // for url substitution
std::vector<SubstItem> subst_smalllet; // changing from small to capital
std::vector<SubstItem> subst_capitallet; // changing from capital to small
std::vector<SubstItem> subst_sort; // local characters for comparison
pt::Space temp_space;
pt::SpaceParser loc_parser;
std::string locale_filea;
std::string file_name;
std::wstring key_str;
const std::wstring empty; // used when returning a non existing key from loc_tab (or in LangToFileName)
std::string adir1, adir2;
std::wstring pattern_value;
};
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool Locale::IsKey(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
bool try_default_too)
{
key.to_str(key_str);
return IsKey(key_str, try_default_too);
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool Locale::IsKey(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
size_t lang_id, bool try_default_too)
{
key.to_str(key_str);
return IsKey(key_str, lang_id, try_default_too);
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
const std::wstring & Locale::Get(const pt::TextStreamBase<char_type, stack_size, heap_block_size> & key,
bool try_default_too)
{
key.to_str(key_str);
return Get(key_str, try_default_too);
}
} // namespace Winix
#endif