Bump libdcp for build fixes.
[libsub.git] / src / util.cc
1 /*
2     Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "util.h"
21 #include "reader.h"
22 #include "subtitle.h"
23 #include "collect.h"
24 #include <boost/shared_ptr.hpp>
25 #include <string>
26 #include <iostream>
27 #include <cstdio>
28 #include <map>
29
30 using std::string;
31 using std::getline;
32 using std::ostream;
33 using std::map;
34 using std::list;
35 using boost::optional;
36 using boost::shared_ptr;
37 using namespace sub;
38
39 /** @param s A string.
40  *  @return true if the string contains only space, newline or tab characters, or is empty.
41  */
42 bool
43 sub::empty_or_white_space (string s)
44 {
45         for (size_t i = 0; i < s.length(); ++i) {
46                 if (s[i] != ' ' && s[i] != '\n' && s[i] != '\t') {
47                         return false;
48                 }
49         }
50
51         return true;
52 }
53
54 optional<string>
55 sub::get_line_string (string* s)
56 {
57         if (s->length() == 0) {
58                 return optional<string>();
59         }
60
61         size_t pos = s->find ("\n");
62         if (pos == string::npos) {
63                 string const c = *s;
64                 *s = "";
65                 return c;
66         }
67
68         string const c = s->substr (0, pos);
69         s->erase (0, pos + 1);
70         return c;
71 }
72
73 optional<string>
74 sub::get_line_file (FILE* f)
75 {
76         char buffer[256];
77         char* r = fgets (buffer, sizeof (buffer), f);
78         if (r == 0) {
79                 return optional<string> ();
80         }
81
82         return string (buffer);
83 }
84
85 void
86 sub::remove_unicode_bom (optional<string>& line)
87 {
88         if (
89                 line->length() >= 3 &&
90                 static_cast<unsigned char> (line.get()[0]) == 0xef &&
91                 static_cast<unsigned char> (line.get()[1]) == 0xbb &&
92                 static_cast<unsigned char> (line.get()[2]) == 0xbf
93                 ) {
94
95                 /* Skip Unicode byte order mark */
96                 line = line->substr (3);
97         }
98 }
99
100 void
101 sub::dump (shared_ptr<const Reader> reader, ostream& os)
102 {
103         map<string, string> metadata = reader->metadata ();
104         for (map<string, string>::const_iterator i = metadata.begin(); i != metadata.end(); ++i) {
105                 os << i->first << ": " << i->second << "\n";
106         }
107
108         list<sub::Subtitle> subs = collect<list<sub::Subtitle> > (reader->subtitles ());
109         int n = 0;
110         for (list<sub::Subtitle>::const_iterator i = subs.begin(); i != subs.end(); ++i) {
111                 os << "Subtitle " << n << " at " << i->from << " -> " << i->to << "\n";
112                 for (list<sub::Line>::const_iterator j = i->lines.begin(); j != i->lines.end(); ++j) {
113
114                         os << "\t";
115
116                         if (j->vertical_position.proportional) {
117                                 os << j->vertical_position.proportional.get() << " of screen";
118                         } else if (j->vertical_position.line && j->vertical_position.lines) {
119                                 os << j->vertical_position.line.get() << " lines of " << j->vertical_position.lines.get();
120                         }
121                         if (j->vertical_position.reference) {
122                                 os << " from ";
123                                 switch (j->vertical_position.reference.get()) {
124                                 case TOP_OF_SCREEN:
125                                         os << "top";
126                                         break;
127                                 case VERTICAL_CENTRE_OF_SCREEN:
128                                         os << "centre";
129                                         break;
130                                 case BOTTOM_OF_SCREEN:
131                                         os << "bottom";
132                                         break;
133                                 case TOP_OF_SUBTITLE:
134                                         os << "top of subtitle";
135                                         break;
136                                 }
137                         }
138
139                         os << "\t";
140                         bool italic = false;
141                         bool underline = false;
142                         for (list<sub::Block>::const_iterator k = j->blocks.begin(); k != j->blocks.end(); ++k) {
143                                 if (k->italic && !italic) {
144                                         os << "<i>";
145                                 } else if (italic && !k->italic) {
146                                         os << "</i>";
147                                 }
148                                 if (k->underline && !underline) {
149                                         os << "<u>";
150                                 } else if (underline && !k->underline) {
151                                         os << "</u>";
152                                 }
153
154                                 italic = k->italic;
155                                 underline = k->underline;
156
157                                 os << k->text;
158                         }
159
160                         if (italic) {
161                                 os << "</i>";
162                         }
163                         if (underline) {
164                                 os << "</u>";
165                         }
166                         os << "\n";
167                 }
168
169                 ++n;
170         }
171 }