Add a nice note for general MXF errors.
[libdcp.git] / src / 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
35 /** @file  src/language_tag.cc
36  *  @brief LanguageTag class
37  */
38
39
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
53 class LanguageTag
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) const {
72                         return subtag == other.subtag && description == other.description;
73                 }
74
75                 bool operator!=(SubtagData const& other) const {
76                         return subtag != other.subtag || description != other.description;
77                 }
78         };
79
80         enum class SubtagType
81         {
82                 LANGUAGE,
83                 SCRIPT,
84                 REGION,
85                 VARIANT,
86                 EXTLANG,
87         };
88
89         class Subtag
90         {
91         public:
92                 virtual ~Subtag () {}
93
94                 std::string subtag () const {
95                         return _subtag;
96                 }
97
98                 virtual SubtagType type () const = 0;
99
100                 bool operator== (Subtag const& other) const {
101                         return _subtag == other._subtag;
102                 }
103
104                 bool operator!=(Subtag const& other) const {
105                         return _subtag != other._subtag;
106                 }
107
108                 bool operator<(Subtag const& other) const {
109                         return _subtag < other._subtag;
110                 }
111
112         protected:
113                 Subtag (std::string subtag, SubtagType type);
114
115         private:
116                 std::string _subtag;
117         };
118
119         class LanguageSubtag : public Subtag
120         {
121         public:
122                 LanguageSubtag (std::string subtag)
123                         : Subtag(subtag, SubtagType::LANGUAGE) {}
124                 LanguageSubtag (char const* subtag)
125                         : Subtag(subtag, SubtagType::LANGUAGE) {}
126
127                 SubtagType type () const override {
128                         return SubtagType::LANGUAGE;
129                 }
130         };
131
132         class ScriptSubtag : public Subtag
133         {
134         public:
135                 ScriptSubtag (std::string subtag)
136                         : Subtag(subtag, SubtagType::SCRIPT) {}
137                 ScriptSubtag (char const* subtag)
138                         : Subtag(subtag, SubtagType::SCRIPT) {}
139
140                 SubtagType type () const override {
141                         return SubtagType::SCRIPT;
142                 }
143         };
144
145         class RegionSubtag : public Subtag
146         {
147         public:
148                 RegionSubtag (std::string subtag)
149                         : Subtag(subtag, SubtagType::REGION) {}
150                 RegionSubtag (char const* subtag)
151                         : Subtag(subtag, SubtagType::REGION) {}
152
153                 SubtagType type () const override {
154                         return SubtagType::REGION;
155                 }
156         };
157
158         class VariantSubtag : public Subtag
159         {
160         public:
161                 VariantSubtag (std::string subtag)
162                         : Subtag(subtag, SubtagType::VARIANT) {}
163                 VariantSubtag (char const* subtag)
164                         : Subtag(subtag, SubtagType::VARIANT) {}
165
166                 SubtagType type () const override {
167                         return SubtagType::VARIANT;
168                 }
169         };
170
171
172         class ExtlangSubtag : public Subtag
173         {
174         public:
175                 ExtlangSubtag (std::string subtag)
176                         : Subtag(subtag, SubtagType::EXTLANG) {}
177                 ExtlangSubtag (char const* subtag)
178                         : Subtag(subtag, SubtagType::EXTLANG) {}
179
180                 SubtagType type () const override {
181                         return SubtagType::EXTLANG;
182                 }
183         };
184
185         LanguageTag () {}
186         explicit LanguageTag (std::string tag);
187
188         boost::optional<LanguageSubtag> language() const {
189                 return _language;
190         }
191
192         void set_language (LanguageSubtag language);
193
194         boost::optional<ScriptSubtag> script() const {
195                 return _script;
196         }
197
198         void set_script (ScriptSubtag script);
199
200         boost::optional<RegionSubtag> region() const {
201                 return _region;
202         }
203
204         void set_region (RegionSubtag region);
205
206         std::vector<VariantSubtag> variants() const {
207                 return _variants;
208         }
209
210         void set_variants (std::vector<VariantSubtag> variants);
211         void add_variant (VariantSubtag variant);
212
213         std::vector<ExtlangSubtag> extlangs() const {
214                 return _extlangs;
215         }
216
217         void set_extlangs (std::vector<ExtlangSubtag> extlangs);
218         void add_extlang (ExtlangSubtag extlang);
219
220         std::vector<std::pair<SubtagType, SubtagData>> subtags () const;
221
222         static std::vector<SubtagData> const& get_all (SubtagType type);
223         static std::string subtag_type_name (SubtagType type);
224
225         static boost::optional<std::string> get_subtag_description (SubtagType, std::string subtag);
226         static boost::optional<SubtagData> get_subtag_data (SubtagType, std::string subtag);
227
228         template <class T>
229         static boost::optional<std::string> get_subtag_description (T s) {
230                 return get_subtag_description (s.type(), s.subtag());
231         }
232
233         template <class T>
234         static boost::optional<SubtagData> get_subtag_data (T s) {
235                 return get_subtag_data (s.type(), s.subtag());
236         }
237
238 private:
239
240         boost::optional<LanguageSubtag> _language;
241         boost::optional<ScriptSubtag> _script;
242         boost::optional<RegionSubtag> _region;
243         std::vector<VariantSubtag> _variants;
244         std::vector<ExtlangSubtag> _extlangs;
245 };
246
247
248 extern bool operator==(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
249 extern bool operator!=(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
250 extern bool operator<(dcp::LanguageTag const& a, dcp::LanguageTag const& b);
251 extern std::ostream& operator<<(std::ostream& os, dcp::LanguageTag const& tag);
252
253
254 extern void load_language_tag_lists (boost::filesystem::path tags_directory);
255
256
257 extern std::vector<std::pair<std::string, std::string>> dcnc_tags ();
258
259
260 }
261
262
263 #endif