libdcp
language_tag.h
1 /*
2  Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
3 
4  This file is part of libdcp.
5 
6  libdcp is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  libdcp is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with libdcp. If not, see <http://www.gnu.org/licenses/>.
18 
19  In addition, as a special exception, the copyright holders give
20  permission to link the code of portions of this program with the
21  OpenSSL library under certain conditions as described in each
22  individual source file, and distribute linked combinations
23  including the two.
24 
25  You must obey the GNU General Public License in all respects
26  for all of the code used other than OpenSSL. If you modify
27  file(s) with this exception, you may extend this exception to your
28  version of the file(s), but you are not obligated to do so. If you
29  do not wish to do so, delete this exception statement from your
30  version. If you delete this exception statement from all source
31  files in the program, then also delete it here.
32 */
33 
34 
40 #ifndef LIBDCP_LANGUAGE_TAG_H
41 #define LIBDCP_LANGUAGE_TAG_H
42 
43 
44 #include <boost/filesystem.hpp>
45 #include <boost/optional.hpp>
46 #include <string>
47 #include <vector>
48 
49 
50 namespace dcp {
51 
52 
54 {
55 public:
56  std::string to_string () const;
57  std::string description () const;
58 
59  struct SubtagData
60  {
61  SubtagData () {}
62 
63  SubtagData (std::string subtag_, std::string description_)
64  : subtag(subtag_)
65  , description(description_)
66  {}
67 
68  std::string subtag;
69  std::string description;
70 
71  bool operator== (SubtagData const& other) {
72  return subtag == other.subtag && description == other.description;
73  }
74  };
75 
76  enum class SubtagType
77  {
78  LANGUAGE,
79  SCRIPT,
80  REGION,
81  VARIANT,
82  EXTLANG,
83  };
84 
85  class Subtag
86  {
87  public:
88  virtual ~Subtag () {}
89 
90  std::string subtag () const {
91  return _subtag;
92  }
93 
94  virtual SubtagType type () const = 0;
95 
96  bool operator== (Subtag const& other) {
97  return _subtag == other._subtag;
98  }
99 
100  protected:
101  Subtag (std::string subtag, SubtagType type);
102 
103  private:
104  std::string _subtag;
105  };
106 
107  class LanguageSubtag : public Subtag
108  {
109  public:
110  LanguageSubtag (std::string subtag)
111  : Subtag(subtag, SubtagType::LANGUAGE) {}
112  LanguageSubtag (char const* subtag)
113  : Subtag(subtag, SubtagType::LANGUAGE) {}
114 
115  SubtagType type () const override {
116  return SubtagType::LANGUAGE;
117  }
118  };
119 
120  class ScriptSubtag : public Subtag
121  {
122  public:
123  ScriptSubtag (std::string subtag)
124  : Subtag(subtag, SubtagType::SCRIPT) {}
125  ScriptSubtag (char const* subtag)
126  : Subtag(subtag, SubtagType::SCRIPT) {}
127 
128  SubtagType type () const override {
129  return SubtagType::SCRIPT;
130  }
131  };
132 
133  class RegionSubtag : public Subtag
134  {
135  public:
136  RegionSubtag (std::string subtag)
137  : Subtag(subtag, SubtagType::REGION) {}
138  RegionSubtag (char const* subtag)
139  : Subtag(subtag, SubtagType::REGION) {}
140 
141  SubtagType type () const override {
142  return SubtagType::REGION;
143  }
144  };
145 
146  class VariantSubtag : public Subtag
147  {
148  public:
149  VariantSubtag (std::string subtag)
150  : Subtag(subtag, SubtagType::VARIANT) {}
151  VariantSubtag (char const* subtag)
152  : Subtag(subtag, SubtagType::VARIANT) {}
153 
154  SubtagType type () const override {
155  return SubtagType::VARIANT;
156  }
157 
158  bool operator== (VariantSubtag const& other) const;
159  bool operator< (VariantSubtag const& other) const;
160  };
161 
162 
163  class ExtlangSubtag : public Subtag
164  {
165  public:
166  ExtlangSubtag (std::string subtag)
167  : Subtag(subtag, SubtagType::EXTLANG) {}
168  ExtlangSubtag (char const* subtag)
169  : Subtag(subtag, SubtagType::EXTLANG) {}
170 
171  SubtagType type () const override {
172  return SubtagType::EXTLANG;
173  }
174 
175  bool operator== (ExtlangSubtag const& other) const;
176  bool operator< (ExtlangSubtag const& other) const;
177  };
178 
179  LanguageTag () {}
180  explicit LanguageTag (std::string tag);
181 
182  boost::optional<LanguageSubtag> language() const {
183  return _language;
184  }
185 
186  void set_language (LanguageSubtag language);
187 
188  boost::optional<ScriptSubtag> script() const {
189  return _script;
190  }
191 
192  void set_script (ScriptSubtag script);
193 
194  boost::optional<RegionSubtag> region() const {
195  return _region;
196  }
197 
198  void set_region (RegionSubtag region);
199 
200  std::vector<VariantSubtag> variants() const {
201  return _variants;
202  }
203 
204  void set_variants (std::vector<VariantSubtag> variants);
205  void add_variant (VariantSubtag variant);
206 
207  std::vector<ExtlangSubtag> extlangs() const {
208  return _extlangs;
209  }
210 
211  void set_extlangs (std::vector<ExtlangSubtag> extlangs);
212  void add_extlang (ExtlangSubtag extlang);
213 
214  std::vector<std::pair<SubtagType, SubtagData>> subtags () const;
215 
216  static std::vector<SubtagData> const& get_all (SubtagType type);
217  static std::string subtag_type_name (SubtagType type);
218 
219  static boost::optional<std::string> get_subtag_description (SubtagType, std::string subtag);
220  static boost::optional<SubtagData> get_subtag_data (SubtagType, std::string subtag);
221 
222  template <class T>
223  static boost::optional<std::string> get_subtag_description (T s) {
224  return get_subtag_description (s.type(), s.subtag());
225  }
226 
227  template <class T>
228  static boost::optional<SubtagData> get_subtag_data (T s) {
229  return get_subtag_data (s.type(), s.subtag());
230  }
231 
232 private:
233 
234  boost::optional<LanguageSubtag> _language;
235  boost::optional<ScriptSubtag> _script;
236  boost::optional<RegionSubtag> _region;
237  std::vector<VariantSubtag> _variants;
238  std::vector<ExtlangSubtag> _extlangs;
239 };
240 
241 
242 extern bool operator==(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
243 extern bool operator!=(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
244 extern bool operator<(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
245 extern std::ostream& operator<<(std::ostream& os, dcp::LanguageTag const& tag);
246 
247 
248 extern void load_language_tag_lists (boost::filesystem::path tags_directory);
249 
250 
251 extern std::vector<std::pair<std::string, std::string>> dcnc_tags ();
252 
253 
254 }
255 
256 
257 #endif
Namespace for everything in libdcp.
Definition: array_data.h:50