Re: [Boost-bugs] [Boost C++ Libraries] #7266: Gettext path formats.

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #7266: Gettext path formats.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-01-07 06:37:56


#7266: Gettext path formats.
--------------------------------------+-------------------------------------
  Reporter: 166291@… | Owner: artyom
      Type: Patches | Status: assigned
 Milestone: Boost 1.54.0 | Component: locale
   Version: Boost Development Trunk | Severity: Not Applicable
Resolution: | Keywords:
--------------------------------------+-------------------------------------

Comment (by 166291@…):

 Okay, I've thought about this a lot and concluded that path formats are
 the wrong way to go about this in the short term, and only end up with
 technical debt. It should be handled by a callback class that receives
 information about the wanted catalog (locale name. category, etc) and
 returns the bytes of the file, as this is technically about custom file
 system support.

 I haven't actually coded anything yet, but this is how I'll think it'd
 work, and more importantly, why it'd be better:

 {{{
 // --- BOOST.LOCALE CODE

 //! Information about a single catalog we want to find.
 class catalog_info
 {
   string language;
   string country;
   string variant;
   string encoding;
   string locale_category;
   string domain;
 };

 //! Searches for, and loads a catalog.
 class default_catalog_loader
 {
   public:
     void add_search_path(string const& path);
     void add_path_format(string const& path);

     vector<byte> callback(catalog_info& info)
     {
       vector<string> paths;
       paths += language;
       paths += language + "_" + country + "@" + variant;
       paths += language + "@" + variant;
       paths += language + "_" + country;

       foreach(search_path in search_paths)
       {
         foreach(path_format in path_formats)
         {
           foreach(path in paths)
           {
             string formatted = format(insert uber long line from existing
 code);

             if(FILE_EXISTS(formatted))
             {
               // LOAD_FILE is hypothetical and utopian, thus UTF-8
 encoded.
               return LOAD_FILE(formatted));
             }
           }
         }
       }

       return vector<byte>(); // Empty vector.
     }
 }

 // --- USER CODE

 std::locale init_locale(void)
 {
   default_catalog_loader loader;
   loader.add_search_path("/usr/share/locale/");
   loader.add_path_format("{1}/{2}/{3}/{4}.mo");

   generator gen;
   std::locale genLoc = gen("en_US.UTF-8");

   blg::messages_info info;
   info.language = "en";
   info.country = "US";
   info.encoding = "UTF-8";
   info.variant = "@euro";
   info.callback = boost::bind(loader::callback, &loader, _1, _2);

   std::locale gettextLoc(genLoc, blg::create_messages_facet<char>(info));

   return gettextLoc;
 }
 }}}

 That would do what the existing code does (kind of, I'm sure I've
 forgotten something). Plus it means people could do things like this:

 {{{
 // --- USER CODE

 // Include generated headers using bin2hex or something interesting.
 #include "en_US.mo.h"
 #include "en_at_euro.mo.h"

 vector<byte> memory_callback(catalog_info& info)
 {
   vector<string> paths;
   paths += language;
   paths += language + "_" + country + "@" + variant;
   paths += language + "@" + variant;
   paths += language + "_" + country;

   foreach(path in paths)
   {
     byte* file_bytes = GET_MEMORY_FILE(path + ".mo");

     if(file_bytes)
     {
       return VECTOR_FROM_BYTES(file_bytes);
     }
   }

   return vector<byte>(); // Empty vector.
 }
 }}}

 Which implements a simple memory-based file loader. Personally I'd use
 this for my projects, as I already use a callback.

 I have a few notes on this approach however:

 There is shared repetition when looking for paths in multiple callback
 code. I don't know how to remove this without calling the callback
 multiple times, which is against this design (EXCEPT when we're trying to
 load multiple catalogs for multiple domains).

 It'd be stupidly easy to have a get_loaded_catalogs method that implements
 #7727 in the library side, but it'd be best if it had some 'user' callback
 data. In the first case, which path format and search path and formatted
 path, in the second case, a pointer to the memory file.

 messages_info's callback would need to be changed, breaking the ABI.
 However, having a create_messages_facet that ONLY takes a callback in this
 case would work.

 Another thing is whether callbacks be classes?
 While the second example is one function long, making it a class would
 remove the horrible bind for class members, it'd allow the loader to be an
 interface which would be extendable if done right, I imagine callback data
 for catalog_info could be an abstract class defined by the loader too.

 What it'd also allow to do is custom file FORMATS, by returning something
 that mo_messages could use as a string table. This means for example, I
 could write a parser that loads po files uncompiled, or somebody
 completely insane could use XML, which I imagine could help transition.

 What're your thoughts on this?

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/7266#comment:7>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:11 UTC