libshit

Just some random shit
git clone https://git.neptards.moe/neptards/libshit.git
Log | Files | Refs | Submodules | README | LICENSE

context.hpp (3426B)


      1 #ifndef GUARD_UBIQUITOUSLY_HANGABLE_VANITORY_MAMMERS_6659
      2 #define GUARD_UBIQUITOUSLY_HANGABLE_VANITORY_MAMMERS_6659
      3 #pragma once
      4 
      5 #include "libshit/except.hpp"
      6 #include "libshit/nonowning_string.hpp"
      7 #include "libshit/translate/base.hpp"
      8 #include "libshit/translate/defines.hpp"
      9 #include "libshit/translate/plural.hpp"
     10 
     11 #include <boost/container/flat_map.hpp>
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <functional>
     16 #include <iosfwd>
     17 #include <map>
     18 #include <string>
     19 #include <type_traits>
     20 #include <vector>
     21 
     22 #if LIBSHIT_TRANSLATE_YAML
     23 #  include "libshit/yaml.hpp"
     24 #endif
     25 // IWYU pragma: no_forward_declare YAML::convert
     26 
     27 namespace Libshit::Translate
     28 {
     29   class Node;
     30   inline constexpr std::size_t MAX_CASES = 100;
     31 
     32   struct LanguageInfo
     33   {
     34     ~LanguageInfo() noexcept = default;
     35 
     36     // posix: lang[_territory][.codeset][@modifier] (eg. en_US.UTF-8, be_BY.UTF-8@latin)
     37     // windows: lang[-script]-region[_shit] (eg. en-US, uz-Latn-UZ)
     38     // wine ignores @modifier, generated locale has no script
     39     // used by us: lang[_territory]
     40     std::string name, en_name, iso_code;
     41     std::string decimal_sep, digit_sep;
     42     unsigned grouping = 3;
     43     std::vector<std::string> cases;
     44     std::vector<std::string> genders;
     45     std::vector<NotNullSharedPtr<const ASTNode>> plural_exprs;
     46     std::uint8_t plural_count = 1;
     47 
     48     boost::container::flat_map<std::string, std::string> macros;
     49 
     50     LIBSHIT_TRANSLATE_WITH_YAML(void Read(const YAML::Node& node));
     51     LIBSHIT_TRANSLATE_WITH_DUMP(void Dump(std::ostream& os) const);
     52   };
     53 
     54   class Context : public RefCounted
     55   {
     56   public:
     57     Context() noexcept;
     58     // only public for tests
     59     Context(const LanguageInfo& info);
     60     ~Context() noexcept override;
     61 
     62     // workaround having to include Node implementation...
     63     template <bool B = true>
     64     NotNullNodePtr operator[](StringView key) const
     65     { return std::enable_if_t<B, const Context*>(this)->root[key]; }
     66 
     67     LIBSHIT_TRANSLATE_WITH_YAML(void Load(std::istream& is, std::string dir = {}));
     68     LIBSHIT_TRANSLATE_WITH_YAML(void Load(const std::string& fname));
     69 
     70     unsigned GetCaseId(Libshit::StringView str);
     71     unsigned AtCaseId(Libshit::StringView str) const;
     72 
     73     unsigned GetGenderId(Libshit::StringView str) const;
     74     unsigned AtGenderId(Libshit::StringView str) const;
     75 
     76     const LanguageInfo& GetInfo() const noexcept { return info; }
     77     // warning: fucking slow
     78     const std::vector<std::string>& GetNodePath(const Node* ptr);
     79 
     80     NotNullNodePtr GetRoot() const noexcept;
     81 
     82     LIBSHIT_TRANSLATE_WITH_DUMP(void Dump(
     83       StringView ns, StringView name, std::ostream& cpp, std::ostream& hpp,
     84       StringView hpp_name) const);
     85 
     86   protected:
     87     void Dispose() noexcept override;
     88 
     89     LanguageInfo info;
     90     NodePtr root;
     91 
     92   private:
     93     boost::container::flat_map<std::string, unsigned, std::less<>>
     94     case_map, gender_map;
     95     std::map<const Node*, std::vector<std::string>> invalid_cache;
     96   };
     97 
     98   LIBSHIT_GEN_EXCEPTION_TYPE(TranslationError, std::runtime_error);
     99   LIBSHIT_GEN_EXCEPTION_TYPE(LanguageInfoError, TranslationError);
    100 }
    101 
    102 #if LIBSHIT_TRANSLATE_YAML
    103 namespace YAML
    104 {
    105   template <> struct convert<Libshit::Translate::LanguageInfo>
    106   {
    107     using LI = Libshit::Translate::LanguageInfo;
    108     static bool decode(const Node& node, LI& li)
    109     {
    110       try { li.Read(node); return true; }
    111       catch (const Libshit::Translate::TranslationError&) { return false; }
    112     }
    113   };
    114 }
    115 #endif
    116 
    117 #endif