Basic support for parsing in-line markup in SSA.
authorCarl Hetherington <cth@carlh.net>
Mon, 15 Feb 2016 08:39:50 +0000 (08:39 +0000)
committerCarl Hetherington <cth@carlh.net>
Mon, 15 Feb 2016 23:18:23 +0000 (23:18 +0000)
src/ssa_reader.cc
src/ssa_reader.h
test/ssa_reader_test.cc

index d4908a2eacd0fc989f811d40ff6d1e7bbab1876a..703ed266d6a9da41ede364b5e832dd44ada936de 100644 (file)
@@ -34,6 +34,7 @@ using std::stringstream;
 using std::vector;
 using std::map;
 using std::cout;
+using std::list;
 using boost::optional;
 using boost::function;
 using namespace boost::algorithm;
@@ -137,6 +138,68 @@ SSAReader::parse_time (string t) const
                );
 }
 
+list<RawSubtitle>
+SSAReader::parse_line (RawSubtitle base, string line)
+{
+       enum {
+               TEXT,
+               STYLE,
+               BACKSLASH
+       } state = TEXT;
+
+       list<RawSubtitle> subs;
+       RawSubtitle current = base;
+       string style;
+
+       current.vertical_position.line = 0;
+
+       for (size_t i = 0; i < line.length(); ++i) {
+               char const c = line[i];
+               switch (state) {
+               case TEXT:
+                       if (c == '{') {
+                               state = STYLE;
+                       } else if (c == '\\') {
+                               state = BACKSLASH;
+                       } else {
+                               current.text += c;
+                       }
+                       break;
+               case STYLE:
+                       if (c == '}') {
+                               if (!current.text.empty ()) {
+                                       subs.push_back (current);
+                                       current.text = "";
+                               }
+                               if (style == "i1") {
+                                       current.italic = true;
+                               } else if (style == "i0") {
+                                       current.italic = false;
+                               }
+                               style = "";
+                               state = TEXT;
+                       } else {
+                               style += c;
+                       }
+                       break;
+               case BACKSLASH:
+                       if (c == 'n' && !current.text.empty ()) {
+                               subs.push_back (current);
+                               current.text = "";
+                               current.vertical_position.line = current.vertical_position.line.get() + 1;
+                       }
+                       state = TEXT;
+                       break;
+               }
+       }
+
+       if (!current.text.empty ()) {
+               subs.push_back (current);
+       }
+
+       return subs;
+}
+
 void
 SSAReader::read (function<optional<string> ()> get_line)
 {
index 0f575ff0961979c5fe49d21fb2e79865793a9ec2..1fe64f371b40820377be6bd8f3ee437d25ae5a9a 100644 (file)
@@ -35,6 +35,8 @@ public:
        SSAReader (FILE* f);
        SSAReader (std::string const & subs);
 
+       static std::list<RawSubtitle> parse_line (RawSubtitle base, std::string line);
+
 private:
        void read (boost::function<boost::optional<std::string> ()> get_line);
        Time parse_time (std::string t) const;
index c7594d7a168ca885ee1da4ca4c6b413325b91a4d..97626a68ad1add142c4891ae39b4eb1cc7ca6164 100644 (file)
@@ -69,3 +69,41 @@ BOOST_AUTO_TEST_CASE (ssa_reader_test)
 
        BOOST_CHECK (i == subs.end());
 }
+
+BOOST_AUTO_TEST_CASE (ssa_reader_line_test1)
+{
+       sub::RawSubtitle base;
+       list<sub::RawSubtitle> r = sub::SSAReader::parse_line (base, "This is a line with some {i1}italics{i0} and then\\nthere is a new line.");
+
+       list<sub::RawSubtitle>::const_iterator i = r.begin ();
+       BOOST_CHECK_EQUAL (i->text, "This is a line with some ");
+       BOOST_CHECK_EQUAL (i->italic, false);
+       ++i;
+       BOOST_REQUIRE (i != r.end ());
+
+       BOOST_CHECK_EQUAL (i->text, "italics");
+       BOOST_CHECK_EQUAL (i->italic, true);
+       ++i;
+       BOOST_REQUIRE (i != r.end ());
+
+       BOOST_CHECK_EQUAL (i->text, " and then");
+       BOOST_CHECK_EQUAL (i->italic, false);
+       ++i;
+       BOOST_REQUIRE (i != r.end ());
+
+       BOOST_CHECK_EQUAL (i->text, "there is a new line.");
+       ++i;
+       BOOST_REQUIRE (i == r.end ());
+}
+
+BOOST_AUTO_TEST_CASE (ssa_reader_line_test2)
+{
+       sub::RawSubtitle base;
+       list<sub::RawSubtitle> r = sub::SSAReader::parse_line (base, "{i1}It's all just italics{i0}");
+
+       list<sub::RawSubtitle>::const_iterator i = r.begin ();
+       BOOST_CHECK_EQUAL (i->text, "It's all just italics");
+       BOOST_CHECK_EQUAL (i->italic, true);
+       ++i;
+       BOOST_REQUIRE (i == r.end ());
+}