Tidying.
[libdcp.git] / src / language_tag.h
1 /*
2     Copyright (C) 2020 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) {
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 {
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 {
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 {
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 {
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 {
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 std::ostream& operator<<(std::ostream& os, dcp::LanguageTag const& tag);
244
245
246 extern void load_language_tag_lists (boost::filesystem::path tags_directory);
247
248
249 }
250
251 #endif