Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / Locale.cc
index d1e6f66..d564ee1 100644 (file)
@@ -19,208 +19,228 @@ using std::endl;
 
 ///////////////////////////////////////////////////////////////////
 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
 ///////////////////////////////////////////////////////////////////