///////////////////////////////////////////////////////////////////
namespace zypp
-{
- /** Wrap static codemap data. */
- struct CodeMaps
- {
- /** Return IdString without trailing garbage. */
- static IdString withoutTrash( IdString code_r )
- {
- boost::string_ref::size_type sep = trashStart( code_r );
- if ( sep != boost::string_ref::npos )
- code_r = IdString( code_r.c_str(), sep );
- return code_r;
- }
+{ /////////////////////////////////////////////////////////////////
- /** Return IdString without trailing garbage. */
- static IdString withoutTrash( const std::string & code_r )
- { return withoutTrash( boost::string_ref(code_r) ); }
+ typedef std::map<std::string, std::string> OtherDefaultLanguage;
+ static OtherDefaultLanguage otherDefaultLanguage;
- /** Return IdString without trailing garbage. */
- static IdString withoutTrash( const char * code_r )
- { return( code_r ? withoutTrash( boost::string_ref(code_r) ) : IdString::Null ); }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : Locale::Impl
+ //
+ /** Locale implementation. */
+ struct Locale::Impl
+ {
+ Impl()
+ {}
- /** Return IdString from language/country codes. */
- static IdString combineLC( LanguageCode language_r, CountryCode country_r )
+ Impl( const std::string & code_r )
{
- IdString ret;
- if ( language_r )
- {
- if ( country_r )
- ret = IdString( std::string(language_r) + "_" + country_r.c_str() );
- else
- ret = IdString(language_r);
+ std::string t;
+ std::string::size_type sep = code_r.find_first_of( "@." );
+ if ( sep == std::string::npos ) {
+ t = code_r;
+ } else {
+ t = code_r.substr( 0, sep );
}
- else
- {
- if ( country_r )
- ret = IdString( "_" + std::string(country_r) );
- else if ( ! ( IdString(language_r) || IdString(country_r) ) )
- ret = IdString::Null;
- // else IdString::Empty
+
+ sep = t.find( '_' );
+ if ( sep == std::string::npos ) {
+ _language = LanguageCode( t );
+ } else {
+ _language = LanguageCode( t.substr( 0, sep ) );
+ _country = CountryCode( t.substr( sep+1 ) );
}
- return ret;
}
- /** The singleton */
- static CodeMaps & instance()
- {
- static CodeMaps _instance;
- return _instance;
- }
+ Impl( const LanguageCode & language_r,
+ const CountryCode & country_r )
+ : _language( language_r )
+ , _country( country_r )
+ {}
- LanguageCode language( IdString index_r )
- { return getIndex( index_r )._l; }
+ const LanguageCode & language() const
+ { return _language; }
- CountryCode country( IdString index_r )
- { return getIndex( index_r )._c; }
+ const CountryCode & country() const
+ { return _country; }
- std::string name( IdString index_r )
+ std::string code() const
{
- const LC & lc( getIndex( index_r ) );
- std::string ret( lc._l.name() );
- if ( lc._c )
- {
- ret += " (";
- ret += lc._c.name();
- ret += ")";
- }
+ std::string ret( _language.code() );
+ if ( _country.hasCode() )
+ ret += "_" + _country.code();
return ret;
}
- Locale fallback( IdString index_r )
+ std::string name() const
{
- static const IdString special( "pt_BR" );
- Locale ret;
- if ( index_r == special ) // "pt_BR"->"en" - by now the only fallback exception
- ret = Locale::enCode;
- else
- {
- const LC & lc( getIndex( index_r ) );
- if ( lc._c )
- ret = lc._l;
- else if ( lc._l && lc._l != LanguageCode::enCode )
- ret = Locale::enCode;
- }
+ std::string ret( _language.name() );
+ if ( _country.hasCode() )
+ ret += " (" + _country.name() + ")";
return ret;
}
- private:
- static IdString withoutTrash( boost::string_ref code_r )
+ Locale fallback() const
{
- boost::string_ref::size_type sep = trashStart( code_r );
- if ( sep != boost::string_ref::npos )
- code_r = code_r.substr( 0, sep );
- return IdString( code_r );
- }
+ if (otherDefaultLanguage.size() == 0) {
+ // initial inserting map
+ otherDefaultLanguage["pt_BR"] = "en";
+ }
- static boost::string_ref::size_type trashStart( boost::string_ref code_r )
- { return code_r.find_first_of( "@." ); }
+ if (otherDefaultLanguage.find(code()) != otherDefaultLanguage.end())
+ return LanguageCode(otherDefaultLanguage[code()]);
- static boost::string_ref::size_type trashStart( IdString code_r )
- { return trashStart( boost::string_ref(code_r.c_str()) ); }
+ if ( _country.hasCode() )
+ return _language;
- private:
- struct LC {
- LC() {}
- LC( LanguageCode l_r ) : _l( l_r ) {}
- LC( LanguageCode l_r, CountryCode c_r ) : _l( l_r ), _c( c_r ) {}
- LanguageCode _l;
- CountryCode _c;
- };
- typedef std::unordered_map<IdString,LC> CodeMap;
-
- /** Ctor initializes the code maps. */
- CodeMaps()
- : _codeMap( { { IdString::Null, LC( LanguageCode(IdString::Null), CountryCode(IdString::Null) ) }
- , { IdString::Empty, LC( LanguageCode(IdString::Empty), CountryCode(IdString::Empty) ) } } )
- {}
+ if ( _language.hasCode() && _language != LanguageCode("en") )
+ return LanguageCode("en");
- /** Return \ref LC for \a index_r, creating it if necessary. */
- const LC & getIndex( IdString index_r )
- {
- auto it = _codeMap.find( index_r );
- if ( it == _codeMap.end() )
- {
- CodeMap::value_type newval( index_r, LC() );
-
- boost::string_ref str( index_r.c_str() );
- boost::string_ref::size_type sep = str.find( '_' );
- if ( sep == boost::string_ref::npos )
- newval.second._l = LanguageCode( IdString(index_r) );
- else
- {
- newval.second._l = LanguageCode( IdString(str.substr( 0, sep )) );
- newval.second._c = CountryCode( IdString(str.substr( sep+1 )) );
- }
-
- it = _codeMap.insert( std::move(newval) ).first;
- }
- return it->second;
+ return Locale();
}
private:
- CodeMap _codeMap;
+
+ LanguageCode _language;
+ CountryCode _country;
+
+ public:
+ /** Offer default Impl. */
+ static shared_ptr<Impl> nullimpl()
+ {
+ static shared_ptr<Impl> _nullimpl( new Impl );
+ return _nullimpl;
+ }
};
+ ///////////////////////////////////////////////////////////////////
+
+ /** \relates Locale::Impl Stream output */
+ inline std::ostream & operator<<( std::ostream & str, const Locale::Impl & obj )
+ {
+ return str << "Locale::Impl";
+ }
///////////////////////////////////////////////////////////////////
- // class Locale
+ //
+ // CLASS NAME : Locale
+ //
///////////////////////////////////////////////////////////////////
const Locale Locale::noCode;
- const LanguageCode LanguageCode::enCode("en"); // from in LanguageCode.cc as Locale::enCode depends on it
- const Locale Locale::enCode( LanguageCode::enCode );
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::Locale
+ // METHOD TYPE : Ctor
+ //
Locale::Locale()
+ : _pimpl( Impl::nullimpl() )
{}
- Locale::Locale( IdString str_r )
- : _str( CodeMaps::withoutTrash( str_r ) )
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::Locale
+ // METHOD TYPE : Ctor
+ //
+ Locale::Locale( IdString code_r )
+ : _pimpl( new Impl( code_r.asString() ) )
{}
- Locale::Locale( const std::string & str_r )
- : _str( CodeMaps::withoutTrash( str_r ) )
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::Locale
+ // METHOD TYPE : Ctor
+ //
+ Locale::Locale( const std::string & code_r )
+ : _pimpl( new Impl( code_r ) )
{}
- Locale::Locale( const char * str_r )
- : _str( CodeMaps::withoutTrash( str_r ) )
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::Locale
+ // METHOD TYPE : Ctor
+ //
+ Locale::Locale( const char * code_r )
+ : _pimpl( new Impl( C_Str(code_r).c_str() ) )
{}
- Locale::Locale( LanguageCode language_r, CountryCode country_r )
- : _str( CodeMaps::combineLC( language_r, country_r ) )
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::Locale
+ // METHOD TYPE : Ctor
+ //
+ Locale::Locale( const LanguageCode & language_r,
+ const CountryCode & country_r )
+ : _pimpl( new Impl( language_r, country_r ) )
{}
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::~Locale
+ // METHOD TYPE : Dtor
+ //
Locale::~Locale()
{}
- LanguageCode Locale::language() const
- { return CodeMaps::instance().language( _str ); }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::
+ // METHOD TYPE :
+ //
+ const LanguageCode & Locale::language() const
+ { return _pimpl->language(); }
- CountryCode Locale::country() const
- { return CodeMaps::instance().country( _str ); }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::
+ // METHOD TYPE :
+ //
+ const CountryCode & Locale::country() const
+ { return _pimpl->country(); }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::
+ // METHOD TYPE :
+ //
+ std::string Locale::code() const
+ { return _pimpl->code(); }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::
+ // METHOD TYPE :
+ //
std::string Locale::name() const
- { return CodeMaps::instance().name( _str ); }
+ { return _pimpl->name(); }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : Locale::
+ // METHOD TYPE :
+ //
Locale Locale::fallback() const
- { return CodeMaps::instance().fallback( _str ); }
+ { return _pimpl->fallback(); }
+
///////////////////////////////////////////////////////////////////
- Locale Locale::bestMatch( const LocaleSet & avLocales_r, Locale requested_r )
+ Locale Locale::bestMatch( const LocaleSet & avLocales_r, const Locale & requested_r )
{
if ( ! avLocales_r.empty() )
{
- if ( ! requested_r )
- requested_r = ZConfig::instance().textLocale();
- for ( ; requested_r; requested_r = requested_r.fallback() )
+ for ( Locale check( requested_r == noCode ? ZConfig::instance().textLocale() : requested_r );
+ check != noCode; check = check.fallback() )
{
- if ( avLocales_r.count( requested_r ) )
- return requested_r;
+ if ( avLocales_r.find( check ) != avLocales_r.end() )
+ return check;
}
}
- return Locale();
+ return noCode;
}
+
+ /////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////