Replace ContentKind enum with a class.
authorCarl Hetherington <cth@carlh.net>
Fri, 2 Sep 2022 20:43:19 +0000 (22:43 +0200)
committerCarl Hetherington <cth@carlh.net>
Fri, 2 Sep 2022 20:43:19 +0000 (22:43 +0200)
src/content_kind.cc [new file with mode: 0644]
src/content_kind.h [new file with mode: 0644]
src/cpl.cc
src/cpl.h
src/types.cc
src/types.h
src/wscript
test/stream_operators.cc
test/stream_operators.h
test/util_test.cc

diff --git a/src/content_kind.cc b/src/content_kind.cc
new file mode 100644 (file)
index 0000000..4b0da53
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+    Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+    This file is part of libdcp.
+
+    libdcp is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libdcp is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of portions of this program with the
+    OpenSSL library under certain conditions as described in each
+    individual source file, and distribute linked combinations
+    including the two.
+
+    You must obey the GNU General Public License in all respects
+    for all of the code used other than OpenSSL.  If you modify
+    file(s) with this exception, you may extend this exception to your
+    version of the file(s), but you are not obligated to do so.  If you
+    do not wish to do so, delete this exception statement from your
+    version.  If you delete this exception statement from all source
+    files in the program, then also delete it here.
+*/
+
+
+#include "content_kind.h"
+#include "dcp_assert.h"
+#include <algorithm>
+#include <iostream>
+
+
+using std::string;
+using std::vector;
+using namespace dcp;
+
+
+ContentKind const ContentKind::FEATURE                     = ContentKind{"feature"};
+ContentKind const ContentKind::SHORT                       = ContentKind{"short"};
+ContentKind const ContentKind::TRAILER                     = ContentKind{"trailer"};
+ContentKind const ContentKind::TEST                        = ContentKind{"test"};
+ContentKind const ContentKind::TRANSITIONAL                = ContentKind{"transitional"};
+ContentKind const ContentKind::RATING                      = ContentKind{"rating"};
+ContentKind const ContentKind::TEASER                      = ContentKind{"teaser"};
+ContentKind const ContentKind::POLICY                      = ContentKind{"policy"};
+ContentKind const ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT = ContentKind{"psa"};
+ContentKind const ContentKind::ADVERTISEMENT               = ContentKind{"advertisement"};
+ContentKind const ContentKind::EPISODE                     = ContentKind{"episode"};
+ContentKind const ContentKind::PROMO                       = ContentKind{"promo"};
+
+
+vector<ContentKind>
+ContentKind::all()
+{
+       return {
+               ContentKind::FEATURE,
+               ContentKind::SHORT,
+               ContentKind::TRAILER,
+               ContentKind::TEST,
+               ContentKind::TRANSITIONAL,
+               ContentKind::RATING,
+               ContentKind::TEASER,
+               ContentKind::POLICY,
+               ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT,
+               ContentKind::ADVERTISEMENT,
+               ContentKind::EPISODE,
+               ContentKind::PROMO
+       };
+}
+
+
+ContentKind
+ContentKind::from_name(string name)
+{
+       auto const all_kinds = all();
+       std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+       auto iter = std::find_if(all_kinds.begin(), all_kinds.end(), [&name](ContentKind const& k) { return k.name() == name; });
+       if (iter == all_kinds.end()) {
+               throw BadContentKindError(name);
+       }
+       return *iter;
+}
+
+
+bool
+dcp::operator==(ContentKind const& a, ContentKind const& b)
+{
+       return a.name() == b.name();
+}
+
+
+bool
+dcp::operator!=(ContentKind const& a, ContentKind const& b)
+{
+       return !(a == b);
+}
+
+
diff --git a/src/content_kind.h b/src/content_kind.h
new file mode 100644 (file)
index 0000000..08aa17b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+    Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+    This file is part of libdcp.
+
+    libdcp is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    libdcp is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of portions of this program with the
+    OpenSSL library under certain conditions as described in each
+    individual source file, and distribute linked combinations
+    including the two.
+
+    You must obey the GNU General Public License in all respects
+    for all of the code used other than OpenSSL.  If you modify
+    file(s) with this exception, you may extend this exception to your
+    version of the file(s), but you are not obligated to do so.  If you
+    do not wish to do so, delete this exception statement from your
+    version.  If you delete this exception statement from all source
+    files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_CONTENT_KIND_H
+#define LIBDCP_CONTENT_KIND_H
+
+
+#include <boost/optional.hpp>
+#include <string>
+#include <vector>
+
+
+namespace dcp {
+
+
+class ContentKind
+{
+public:
+       std::string name() const {
+               return _name;
+       }
+
+       static const ContentKind FEATURE;
+       static const ContentKind SHORT;
+       static const ContentKind TRAILER;
+       static const ContentKind TEST;
+       static const ContentKind TRANSITIONAL;
+       static const ContentKind RATING;
+       static const ContentKind TEASER;
+       static const ContentKind POLICY;
+       static const ContentKind PUBLIC_SERVICE_ANNOUNCEMENT;
+       static const ContentKind ADVERTISEMENT;
+       static const ContentKind EPISODE;
+       static const ContentKind PROMO;
+
+       static ContentKind from_name(std::string name);
+       static std::vector<ContentKind> all();
+
+private:
+       explicit ContentKind(std::string name)
+               : _name(name)
+       {}
+
+       std::string _name;
+};
+
+
+bool operator==(ContentKind const& a, ContentKind const& b);
+bool operator!=(ContentKind const& a, ContentKind const& b);
+
+
+}
+
+
+#endif
+
index 1c449f8fc5a3eb3e4e08ba7c3f49fbb91864011f..5e0ca2ccd70c1a49476a70c6a4e41c3973e5c986 100644 (file)
@@ -122,7 +122,7 @@ CPL::CPL (boost::filesystem::path file)
        _creator = f.optional_string_child("Creator").get_value_or("");
        _issue_date = f.string_child ("IssueDate");
        _content_title_text = f.string_child ("ContentTitleText");
-       _content_kind = content_kind_from_string (f.string_child ("ContentKind"));
+       _content_kind = ContentKind::from_name(f.string_child("ContentKind"));
        shared_ptr<cxml::Node> content_version = f.optional_node_child ("ContentVersion");
        if (content_version) {
                /* XXX: SMPTE should insist that Id is present */
@@ -198,7 +198,7 @@ CPL::write_xml (boost::filesystem::path file, shared_ptr<const CertificateChain>
        root->add_child("Issuer")->add_child_text (_issuer);
        root->add_child("Creator")->add_child_text (_creator);
        root->add_child("ContentTitleText")->add_child_text (_content_title_text);
-       root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind));
+       root->add_child("ContentKind")->add_child_text(_content_kind.name());
        if (_content_versions.empty()) {
                ContentVersion cv;
                cv.as_xml (root);
index 74bac5f1d6268f072a1207854a82453f5402cb6e..c1489a2c0e8efbffa58f31e020205b63bef607a2 100644 (file)
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -43,6 +43,7 @@
 
 #include "asset.h"
 #include "certificate.h"
+#include "content_kind.h"
 #include "key.h"
 #include "language_tag.h"
 #include "rating.h"
index d3be8a3d1767eeb08ae06c5c29203302a4ea51cf..15a05f79710f378acb51075515b435d79bd851d8 100644 (file)
@@ -293,85 +293,6 @@ dcp::string_to_direction (string s)
 }
 
 
-/** Convert a content kind to a string which can be used in a
- *  &lt;ContentKind&gt; node
- *  @param kind ContentKind
- *  @return string
- */
-string
-dcp::content_kind_to_string (ContentKind kind)
-{
-       switch (kind) {
-       case ContentKind::FEATURE:
-               return "feature";
-       case ContentKind::SHORT:
-               return "short";
-       case ContentKind::TRAILER:
-               return "trailer";
-       case ContentKind::TEST:
-               return "test";
-       case ContentKind::TRANSITIONAL:
-               return "transitional";
-       case ContentKind::RATING:
-               return "rating";
-       case ContentKind::TEASER:
-               return "teaser";
-       case ContentKind::POLICY:
-               return "policy";
-       case ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT:
-               return "psa";
-       case ContentKind::ADVERTISEMENT:
-               return "advertisement";
-       case ContentKind::EPISODE:
-               return "episode";
-       case ContentKind::PROMO:
-               return "promo";
-       }
-
-       DCP_ASSERT (false);
-}
-
-
-/** Convert a string from a &lt;ContentKind&gt; node to a libdcp ContentKind.
- *  Reasonably tolerant about varying case
- *  @param kind Content kind string
- *  @return libdcp ContentKind
- */
-dcp::ContentKind
-dcp::content_kind_from_string (string kind)
-{
-       transform (kind.begin(), kind.end(), kind.begin(), ::tolower);
-
-       if (kind == "feature") {
-               return ContentKind::FEATURE;
-       } else if (kind == "short") {
-               return ContentKind::SHORT;
-       } else if (kind == "trailer") {
-               return ContentKind::TRAILER;
-       } else if (kind == "test") {
-               return ContentKind::TEST;
-       } else if (kind == "transitional") {
-               return ContentKind::TRANSITIONAL;
-       } else if (kind == "rating") {
-               return ContentKind::RATING;
-       } else if (kind == "teaser") {
-               return ContentKind::TEASER;
-       } else if (kind == "policy") {
-               return ContentKind::POLICY;
-       } else if (kind == "psa") {
-               return ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT;
-       } else if (kind == "advertisement") {
-               return ContentKind::ADVERTISEMENT;
-       } else if (kind == "episode") {
-               return ContentKind::EPISODE;
-       } else if (kind == "promo") {
-               return ContentKind::PROMO;
-       }
-
-       throw BadContentKindError (kind);
-}
-
-
 string
 dcp::marker_to_string (dcp::Marker m)
 {
index b6335546c4f3f9aab291ac6288c60fc548f638e5..32f1bfc40a8bc9d74337fd50f509832040ef333f 100644 (file)
@@ -129,27 +129,6 @@ extern std::string channel_to_mca_name (Channel c, MCASoundField field);
 extern ASDCP::UL channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict);
 
 
-enum class ContentKind
-{
-       FEATURE,
-       SHORT,
-       TRAILER,
-       TEST,
-       TRANSITIONAL,
-       RATING,
-       TEASER,
-       POLICY,
-       PUBLIC_SERVICE_ANNOUNCEMENT,
-       ADVERTISEMENT,
-       EPISODE,
-       PROMO
-};
-
-
-extern std::string content_kind_to_string (ContentKind kind);
-extern ContentKind content_kind_from_string (std::string kind);
-
-
 enum class Effect
 {
        NONE,
index 31d83115539cd430b31e916712e11cd24fadb68a..e74c3241d56d7f20e8319eb1f875a85209049a42 100644 (file)
@@ -47,6 +47,7 @@ def build(bld):
              chromaticity.cc
              colour_conversion.cc
              combine.cc
+             content_kind.cc
              cpl.cc
              data.cc
              dcp.cc
@@ -138,6 +139,7 @@ def build(bld):
               colour_conversion.h
               combine.h
               compose.hpp
+              content_kind.h
               cpl.h
               crypto_context.h
               data.h
index 5e4f88e62a8e2a1a92ddbf4f5490da4466f3f9d9..20470c1da405f72b652cd3b21e71ddfceff79a7d 100644 (file)
@@ -81,7 +81,7 @@ dcp::operator<< (std::ostream& s, Effect e)
 ostream&
 dcp::operator<< (ostream& s, ContentKind c)
 {
-       s << content_kind_to_string(c);
+       s << c.name();
        return s;
 }
 
index 691e3daad1566b87c961b2fdfe627a8428ef0c84..d51fa007d156f57b03f2d676eadbcf9d311e943f 100644 (file)
@@ -32,6 +32,7 @@
 */
 
 
+#include "content_kind.h"
 #include "rating.h"
 #include "types.h"
 #include "verify.h"
index 8ca7df44f4cf2d6ddb70e4feb14325d10471a9dd..c31d1d2b3341b96dd13bd22022c8e2b9cff6e18e 100644 (file)
@@ -73,21 +73,21 @@ BOOST_AUTO_TEST_CASE (base64_decode_test)
        }
 }
 
-/** Test dcp::content_kind_from_string */
+/** Test ContentKind::from_name */
 BOOST_AUTO_TEST_CASE (content_kind_test)
 {
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("feature"), dcp::ContentKind::FEATURE);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("Feature"), dcp::ContentKind::FEATURE);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("FeaturE"), dcp::ContentKind::FEATURE);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("Short"), dcp::ContentKind::SHORT);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("trailer"), dcp::ContentKind::TRAILER);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("test"), dcp::ContentKind::TEST);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("transitional"), dcp::ContentKind::TRANSITIONAL);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("rating"), dcp::ContentKind::RATING);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("teaser"), dcp::ContentKind::TEASER);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("policy"), dcp::ContentKind::POLICY);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("psa"), dcp::ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT);
-       BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("advertisement"), dcp::ContentKind::ADVERTISEMENT);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("feature"), dcp::ContentKind::FEATURE);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("Feature"), dcp::ContentKind::FEATURE);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("FeaturE"), dcp::ContentKind::FEATURE);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("Short"), dcp::ContentKind::SHORT);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("trailer"), dcp::ContentKind::TRAILER);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("test"), dcp::ContentKind::TEST);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("transitional"), dcp::ContentKind::TRANSITIONAL);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("rating"), dcp::ContentKind::RATING);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("teaser"), dcp::ContentKind::TEASER);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("policy"), dcp::ContentKind::POLICY);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("psa"), dcp::ContentKind::PUBLIC_SERVICE_ANNOUNCEMENT);
+       BOOST_CHECK_EQUAL(dcp::ContentKind::from_name("advertisement"), dcp::ContentKind::ADVERTISEMENT);
 }
 
 /** Test dcp::relative_to_root */