Expand Up
@@ -37,12 +37,16 @@
#include < cstdio>
#include < cstdlib>
#include < cstring>
#include < iostream>
#include < fcntl.h>
#include < cctype>
#include < sys/stat.h>
#include < sys/types.h>
#include < unistd.h>
#include " captions/xine_demux_sputext.h"
#include " mythlogging.h"
#define LOG_MODULE " demux_sputext"
#define LOG_VERBOSE
/*
Expand All
@@ -61,33 +65,25 @@ static bool eol(char p) {
return (p==' \r ' || p==' \n ' || p==' \0 ' );
}
static inline void trail_space (char *s) {
while (isspace (*s)) {
char *copy = s;
do {
// The clang-tidy warning is wrong. All callers have a null
// terminated string. If the null is the first character in the
// string, this loop is never called. If not, there's
// guaranteed to at least be a second character, even if that
// second character is the null.
// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
copy[0 ] = copy[1 ];
copy++;
} while (*copy != 0 );
}
int i = strlen (s) - 1 ;
while (i > 0 && isspace (s[i]))
s[i--] = ' \0 ' ;
static inline void trail_space (std::string& str)
{
auto mark = str.find_last_of (" \t\r\n " );
if (mark != std::string::npos)
str.erase (mark);
mark = str.find_first_not_of (" \t\r\n " );
if (mark != std::string::npos)
str.erase (0 , mark);
}
/*
* Reimplementation of fgets() using the input->read() method.
*
*/
static char *read_line_from_input (demux_sputext_t *demuxstr, char * line, off_t len ) {
static char *read_line_from_input (demux_sputext_t *demuxstr, std::string& line) {
off_t nread = 0 ;
if ((len - demuxstr->buflen ) > 512 ) {
nread = len - demuxstr->buflen ;
line.reserve (LINE_LEN);
if ((line.capacity () - demuxstr->buflen ) > 512 ) {
nread = line.capacity () - demuxstr->buflen ;
nread = std::min (nread, demuxstr->rbuffer_len - demuxstr->rbuffer_cur );
if (nread < 0 ) {
printf (" read failed.\n " );
Expand All
@@ -103,17 +99,18 @@ static char *read_line_from_input(demux_sputext_t *demuxstr, char *line, off_t l
char *s = strchr (demuxstr->buf , ' \n ' );
if (line && ( s || demuxstr->buflen )) {
if (s || ( demuxstr->buflen > 0 )) {
int linelen = s ? (s - demuxstr->buf ) + 1 : demuxstr->buflen ;
size_t linelen = s ? (s - demuxstr->buf ) + 1 : demuxstr->buflen ;
linelen = std::min (linelen, line.capacity ());
memcpy ( line, demuxstr-> buf , linelen);
line[linelen] = ' \0 ' ;
line. resize ( linelen);
memcpy ( line. data (), demuxstr-> buf , linelen) ;
memmove (demuxstr->buf , &demuxstr->buf [linelen], SUB_BUFSIZE - linelen);
demuxstr->buflen -= linelen;
return line;
return line. data () ;
}
return nullptr ;
Expand All
@@ -122,18 +119,17 @@ static char *read_line_from_input(demux_sputext_t *demuxstr, char *line, off_t l
static subtitle_t *sub_read_line_sami (demux_sputext_t *demuxstr, subtitle_t *current) {
static std::array< char ,LINE_LEN + 1 > s_line;
static std::string s_line;
static char *s_s = nullptr ;
char text[LINE_LEN + 1 ] ;
std::string text;
char *p = nullptr ;
current->start = 0 ;
current->end = -1 ;
int state = 0 ;
/* read the first line */
if (!s_s)
if (!(s_s = read_line_from_input (demuxstr, s_line. data (), LINE_LEN ))) return nullptr ;
if (!(s_s = read_line_from_input (demuxstr, s_line))) return nullptr ;
do {
switch (state) {
Expand All
@@ -151,31 +147,32 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *demuxstr, subtitle_t *cur
break ;
case 2 : /* find ">" */
if ((s_s = strchr (s_s, ' >' ))) { s_s++; state = 3 ; p = text; continue ; }
if ((s_s = strchr (s_s, ' >' ))) { s_s++; state = 3 ; text. clear () ; continue ; }
break ;
case 3 : /* get all text until '<' appears */
if (*s_s == ' \0 ' ) { break ; }
else if (strncasecmp (s_s, " " , 6 ) == 0 ) { *p++ = ' ' ; s_s += 6 ; }
else if (strncasecmp (s_s, " " , 6 ) == 0 ) { text + = ' ' ; s_s += 6 ; }
else if (*s_s == ' \r ' ) { s_s++; }
else if (strncasecmp (s_s, " <br>" , 4 ) == 0 || *s_s == ' \n ' ) {
*p = ' \0 ' ; p = text; trail_space (text);
if (text[0 ] != ' \0 ' )
current->text .push_back ( strdup (text) );
trail_space (text);
if (!text.empty ())
current->text .push_back (text);
text.clear ();
if (*s_s == ' \n ' ) s_s++; else s_s += 4 ;
}
else if (*s_s == ' <' ) { state = 4 ; }
else *p++ = *s_s++;
else text + = *s_s++;
continue ;
case 4 : /* get current->end or skip <TAG> */
char *q = strcasestr (s_s, " start=" );
if (q) {
current->end = strtol (q + 6 , &q, 0 ) / 10 - 1 ;
*p = ' \0 ' ; trail_space (text);
if (text[ 0 ] != ' \0 ' )
current->text .push_back ( strdup ( text) );
if (current->text .size () > 0 ) { state = 99 ; break ; }
trail_space (text);
if (!text. empty () )
current->text .push_back (text);
if (! current->text .empty () ) { state = 99 ; break ; }
state = 0 ; continue ;
}
s_s = strchr (s_s, ' >' );
Expand All
@@ -184,7 +181,7 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *demuxstr, subtitle_t *cur
}
/* read next line */
if (state != 99 && !(s_s = read_line_from_input (demuxstr, s_line. data (), LINE_LEN )))
if (state != 99 && !(s_s = read_line_from_input (demuxstr, s_line)))
return nullptr ;
} while (state != 99 );
Expand All
@@ -207,6 +204,9 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *demuxstr, subtitle_t *cur
* error.
*/
static char *sub_readtext (char *source, std::string& dest) {
if (source == nullptr )
return nullptr ;
int len=0 ;
char *p=source;
Expand All
@@ -225,18 +225,17 @@ static char *sub_readtext(char *source, std::string& dest) {
static subtitle_t *sub_read_line_microdvd (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[ LINE_LEN + 1 ] ;
char line2[ LINE_LEN + 1 ] ;
std::string line; line. reserve ( LINE_LEN + 1 ) ;
std::string line2; line2. reserve ( LINE_LEN + 1 ) ;
current->end =-1 ;
do {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
} while ((sscanf (line, " {%ld}{}%" LINE_LEN_QUOT " [^\r\n ]" , &(current->start ), line2) !=2 ) &&
(sscanf (line, " {%ld}{%ld}%" LINE_LEN_QUOT " [^\r\n ]" , &(current->start ), &(current->end ),line2) !=3 )
if (!read_line_from_input (demuxstr, line)) return nullptr ;
} while ((sscanf (line. c_str () , " {%ld}{}%" LINE_LEN_QUOT " [^\r\n ]" , &(current->start ), line2. data () ) !=2 ) &&
(sscanf (line. c_str () , " {%ld}{%ld}%" LINE_LEN_QUOT " [^\r\n ]" , &(current->start ), &(current->end ),line2. data () ) !=3 )
);
char *p=line2;
char *next=p;
char *next=line2.data ();
std::string out {};
while ((next = sub_readtext (next, out))) {
if (next==ERR) return (subtitle_t *)ERR;
Expand All
@@ -249,28 +248,28 @@ static subtitle_t *sub_read_line_microdvd(demux_sputext_t *demuxstr, subtitle_t
static subtitle_t *sub_read_line_subviewer (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
int a1=0 ,a2=0 ,a3=0 ,a4=0 ,b1=0 ,b2=0 ,b3=0 ,b4=0 ; // NOLINT(readability-isolate-declaration)
while (true ) {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
if (sscanf (line, " %d:%d:%d.%d,%d:%d:%d.%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 ) {
if (sscanf (line, " %d:%d:%d,%d,%d:%d:%d,%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 )
if (!read_line_from_input (demuxstr, line)) return nullptr ;
if (sscanf (line. c_str () , " %d:%d:%d.%d,%d:%d:%d.%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 ) {
if (sscanf (line. c_str () , " %d:%d:%d,%d,%d:%d:%d,%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 )
continue ;
}
current->start = a1*360000 +a2*6000 +a3*100 +a4;
current->end = b1*360000 +b2*6000 +b3*100 +b4;
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return nullptr ;
char *p=line;
char *p=line. data () ;
while (true ) {
char *q=nullptr ;
int len = 0 ;
for (q=p,len=0 ; *p && *p!=' \r ' && *p!=' \n ' && *p!=' |' &&
(strncasecmp (p," [br]" ,4 ) != 0 ); p++,len++);
current->text .push_back ( std::string ( q, len) );
current->text .emplace_back ( q, len);
if (!*p || *p==' \r ' || *p==' \n ' ) break ;
if (*p==' [' ) while (*p++!=' ]' );
if (*p==' |' ) p++;
Expand All
@@ -281,111 +280,102 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *demuxstr, subtitle_t
}
static subtitle_t *sub_read_line_subrip (demux_sputext_t *demuxstr,subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
int a1=0 ,a2=0 ,a3=0 ,a4=0 ,b1=0 ,b2=0 ,b3=0 ,b4=0 ; // NOLINT(readability-isolate-declaration)
int i = 0 ;
do {
if (!read_line_from_input (demuxstr,line,LINE_LEN ))
if (!read_line_from_input (demuxstr,line))
return nullptr ;
i = sscanf (line," %d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4);
i = sscanf (line. c_str () ," %d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4);
} while (i < 8 );
current->start = a1*360000 +a2*6000 +a3*100 +a4/10 ;
current->end = b1*360000 +b2*6000 +b3*100 +b4/10 ;
int end_sub= 0 ;
bool end_sub = false ;
do {
char *p = nullptr ; /* pointer to the curently read char */
char temp_line[SUB_BUFSIZE] ; /* subtitle line that will be transfered to current->text[i] */
int temp_index = 0 ; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */
temp_line[SUB_BUFSIZE- 1 ]= ' \0 ' ; /* just in case... */
if (! read_line_from_input (demuxstr,line,LINE_LEN))
return (current-> text . size () > 0 ) ? current : nullptr ;
for (temp_index= 0 ,p=line;*p!= ' \0 ' && !end_sub && temp_index<SUB_BUFSIZE;p++) {
std::string temp_line; /* subtitle line that will be transfered to current->text[i] */
temp_line. reserve (SUB_BUFSIZE);
if (! read_line_from_input (demuxstr,line))
return (!current-> text . empty ()) ? current : nullptr ;
for (p=line. data (); *p!= ' \0 ' && !end_sub; p++) {
bool eol = false ;
switch (*p) {
case ' \\ ' :
if (*(p+1 )==' N' || *(p+1 )==' n' ) {
temp_line[temp_index++]= ' \0 ' ; /* end of curent line */
eol = true ;
p++;
} else
temp_line[temp_index++]= *p;
temp_line += *p;
break ;
case ' {' :
// The different code for these if/else clauses is ifdef'd out.
// NOLINTNEXTLINE(bugprone-branch-clone)
if (strncmp (p," {\\ i1}" ,5 ) == 0 ) {
#if 0 /* italic not implemented in renderer, ignore them for now */
if(!strncmp(p,"{\\i1}",5) && temp_index+3<SUB_BUFSIZE) {
temp_line[temp_index++]='<';
temp_line[temp_index++]='i';
temp_line[temp_index++]='>';
#else
if (strncmp (p," {\\ i1}" ,5 ) == 0 ) { // NOLINT(bugprone-branch-clone)
temp_line.append("<i>");
#endif
p+=4 ;
}
#if 0 /* italic not implemented in renderer, ignore them for now */
else if(!strncmp(p,"{\\i0}",5) && temp_index+4<SUB_BUFSIZE) {
temp_line[temp_index++]='<';
temp_line[temp_index++]='/';
temp_line[temp_index++]='i';
temp_line[temp_index++]='>';
#else
else if (strncmp (p," {\\ i0}" ,5 ) == 0 ) {
#if 0 /* italic not implemented in renderer, ignore them for now */
temp_line.append("</i>");
#endif
p+=4 ;
}
else
temp_line[temp_index++]= *p;
temp_line += *p;
break ;
case ' \r ' : /* just ignore '\r's */
break ;
case ' \n ' :
temp_line[temp_index++]= ' \0 ' ;
eol = true ;
break ;
default :
temp_line[temp_index++]= *p;
temp_line += *p;
break ;
}
if (temp_index>0 ) {
if (temp_index==SUB_BUFSIZE)
printf (" Too many characters in a subtitle line\n " );
if (temp_line[temp_index-1 ]==' \0 ' || temp_index==SUB_BUFSIZE) {
if (temp_index>1 ) { /* more than 1 char (including '\0') -> that is a valid one */
current->text .push_back (std::string (temp_line,temp_index));
temp_index=0 ;
} else
end_sub=1 ;
if (eol) {
if (!temp_line.empty ())
{
current->text .push_back (temp_line);
temp_line.clear ();
} else {
end_sub = true ;
}
}
}
} while ( end_sub == 0 );
} while (! end_sub);
return current;
}
static subtitle_t *sub_read_line_vplayer (demux_sputext_t *demuxstr,subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
int a1=0 ,a2=0 ,a3=0 ,b1=0 ,b2=0 ,b3=0 ; // NOLINT(readability-isolate-declaration)
while (current->text .empty ()) {
if ( demuxstr->next_line [0 ] == ' \0 ' ) { /* if the buffer is empty.... */
if ( !read_line_from_input (demuxstr, line, LINE_LEN) ) return nullptr ;
if ( demuxstr->next_line .empty () ) {
/* if the buffer is empty.... */
if ( !read_line_from_input (demuxstr, line) ) return nullptr ;
} else {
/* ... get the current line from buffer. */
strncpy ( line, demuxstr->next_line , LINE_LEN);
line[LINE_LEN] = ' \0 ' ; /* I'm scared. This makes me feel better. */
demuxstr->next_line [0 ] = ' \0 ' ; /* mark the buffer as empty. */
line = demuxstr->next_line ;
demuxstr->next_line .clear ();
}
/* Initialize buffer with next line */
if ( ! read_line_from_input ( demuxstr, demuxstr->next_line , LINE_LEN ) ) {
demuxstr->next_line [ 0 ] = ' \0 ' ;
if ( ! read_line_from_input ( demuxstr, demuxstr->next_line ) ) {
demuxstr->next_line . clear () ;
return nullptr ;
}
if ( (sscanf ( line, " %d:%d:%d:" , &a1, &a2, &a3) < 3 ) ||
(sscanf ( demuxstr->next_line , " %d:%d:%d:" , &b1, &b2, &b3) < 3 ) )
if ( (sscanf ( line. c_str (), " %d:%d:%d:" , &a1, &a2, &a3) < 3 ) ||
(sscanf ( demuxstr->next_line . c_str () , " %d:%d:%d:" , &b1, &b2, &b3) < 3 ) )
continue ;
current->start = a1*360000 +a2*6000 +a3*100 ;
current->end = b1*360000 +b2*6000 +b3*100 ;
if ((current->end - current->start ) > LINE_LEN)
current->end = current->start + LINE_LEN; /* not too long though. */
/* teraz czas na wkopiowanie stringu */
char *p=line;
char *p=line. data () ;
/* finds the body of the subtitle_t */
for (int i=0 ; i<3 ; i++){
char *p2=strchr ( p, ' :' );
Expand All
@@ -411,31 +401,32 @@ static subtitle_t *sub_read_line_rt(demux_sputext_t *demuxstr,subtitle_t *curren
* I couldn't check it since DTD is not included.
* WARNING: full XML parses can be required for proper parsing
*/
char line[LINE_LEN + 1 ] ;
std::string line;
int a1=0 ,a2=0 ,a3=0 ,a4=0 ,b1=0 ,b2=0 ,b3=0 ,b4=0 ; // NOLINT(readability-isolate-declaration)
int plen = 0 ;
while (current->text .empty ()) {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
if (!read_line_from_input (demuxstr, line)) return nullptr ;
/*
* TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0
* to describe the same moment in time. Maybe there are even more formats in use.
*/
if (sscanf (line, R"( <Time Begin="%d:%d:%d.%d" End="%d:%d:%d.%d")" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 )
if (sscanf (line. c_str () , R"( <Time Begin="%d:%d:%d.%d" End="%d:%d:%d.%d")" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8 )
plen=a1=a2=a3=a4=b1=b2=b3=b4=0 ;
if (
(sscanf (line, R"( <%*[tT]ime %*[bB]egin="%d:%d" %*[Ee]nd="%d:%d"%*[^<]<clear/>%n)" ,&a2,&a3,&b2,&b3,&plen) < 4 ) &&
(sscanf (line, R"( <%*[tT]ime %*[bB]egin="%d:%d" %*[Ee]nd="%d:%d.%d"%*[^<]<clear/>%n)" ,&a2,&a3,&b2,&b3,&b4,&plen) < 5 ) &&
(sscanf (line. c_str () , R"( <%*[tT]ime %*[bB]egin="%d:%d" %*[Ee]nd="%d:%d"%*[^<]<clear/>%n)" ,&a2,&a3,&b2,&b3,&plen) < 4 ) &&
(sscanf (line. c_str () , R"( <%*[tT]ime %*[bB]egin="%d:%d" %*[Ee]nd="%d:%d.%d"%*[^<]<clear/>%n)" ,&a2,&a3,&b2,&b3,&b4,&plen) < 5 ) &&
/* (sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen) < 5) && */
(sscanf (line, R"( <%*[tT]ime %*[bB]egin="%d:%d.%d" %*[Ee]nd="%d:%d.%d"%*[^<]<clear/>%n)" ,&a2,&a3,&a4,&b2,&b3,&b4,&plen) < 6 ) &&
(sscanf (line, R"( <%*[tT]ime %*[bB]egin="%d:%d:%d.%d" %*[Ee]nd="%d:%d:%d.%d"%*[^<]<clear/>%n)" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen) < 8 )
(sscanf (line. c_str () , R"( <%*[tT]ime %*[bB]egin="%d:%d.%d" %*[Ee]nd="%d:%d.%d"%*[^<]<clear/>%n)" ,&a2,&a3,&a4,&b2,&b3,&b4,&plen) < 6 ) &&
(sscanf (line. c_str () , R"( <%*[tT]ime %*[bB]egin="%d:%d:%d.%d" %*[Ee]nd="%d:%d:%d.%d"%*[^<]<clear/>%n)" ,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen) < 8 )
)
continue ;
current->start = a1*360000 +a2*6000 +a3*100 +a4/10 ;
current->end = b1*360000 +b2*6000 +b3*100 +b4/10 ;
/* TODO: I don't know what kind of convention is here for marking multiline subs, maybe <br/> like in xml? */
char *next = strstr (line," <clear/>" )+8 ;
size_t index = line.find (" <clear/>" );
char *next = (index != std::string::npos) ? &line[index +8 ] : nullptr ;
std::string out {};
while ((next = sub_readtext (next, out))) {
if (next==ERR)
Expand All
@@ -461,27 +452,28 @@ static subtitle_t *sub_read_line_ssa(demux_sputext_t *demuxstr,subtitle_t *curre
int sec2 = 0 ;
int hunsec2 = 0 ;
int nothing = 0 ;
char line[LINE_LEN + 1 ] ;
char line3[LINE_LEN + 1 ] ;
std::string line;
std::string line3; line3. resize (LINE_LEN) ;
char *tmp = nullptr ;
do {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
} while (sscanf (line, " Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,"
if (!read_line_from_input (demuxstr, line)) return nullptr ;
} while (sscanf (line. data () , " Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,"
" %" LINE_LEN_QUOT " [^\n\r ]" , ¬hing,
&hour1, &min1, &sec1, &hunsec1,
&hour2, &min2, &sec2, &hunsec2,
line3) < 9
line3. data () ) < 9
&&
sscanf (line, " Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,"
sscanf (line. data () , " Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,"
" %" LINE_LEN_QUOT " [^\n\r ]" , ¬hing,
&hour1, &min1, &sec1, &hunsec1,
&hour2, &min2, &sec2, &hunsec2,
line3) < 9 );
line3. data () ) < 9 );
char *line2= strchr (line3, ' ,' );
if (!line2 )
size_t index = line3. find ( ' ,' );
if (index == std::string::npos )
return nullptr ;
char *line2 = &line3[index ];
for (comma = 4 ; comma < s_maxComma; comma ++)
{
Expand All
@@ -500,11 +492,11 @@ static subtitle_t *sub_read_line_ssa(demux_sputext_t *demuxstr,subtitle_t *curre
current->end = 360000 *hour2 + 6000 *min2 + 100 *sec2 + hunsec2;
while (((tmp=strstr (line2, " \\ n" )) != nullptr ) || ((tmp=strstr (line2, " \\ N" )) != nullptr ) ){
current->text .push_back ( std::string ( line2, tmp-line2) );
current->text .emplace_back ( line2, tmp-line2);
line2=tmp+2 ;
}
current->text .push_back (line2);
current->text .emplace_back (line2);
return current;
}
Expand All
@@ -521,78 +513,72 @@ static subtitle_t *sub_read_line_ssa(demux_sputext_t *demuxstr,subtitle_t *curre
*/
static subtitle_t *sub_read_line_pjs (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN + 1 ];
char text[LINE_LEN + 1 ];
char *s = nullptr ;
char *d = nullptr ;
std::string line;
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return nullptr ;
for (s = line; *s && isspace (*s); s++);
if (*s == 0 )
size_t mark = line.find_first_not_of (" \t\r\n " );
if (mark != std::string::npos)
line.erase (0 , mark);
if (line.empty ())
return nullptr ;
if (sscanf (line, " %ld,%ld," , &(current->start ),
if (sscanf (line. data () , " %ld,%ld," , &(current->start ),
&(current->end )) <2 )
return (subtitle_t *)ERR;
/* the files I have are in tenths of second */
current->start *= 10 ;
current->end *= 10 ;
/* walk to the beggining of the string */
for (; *s; s++) if (*s==' ,' ) break ;
if (*s) {
for (s++; *s; s++) if (*s==' ,' ) break ;
if (*s) s++;
}
if (*s!=' "' ) {
return (subtitle_t *)ERR;
}
/* copy the string to the text buffer */
for (s++, d=text; *s && *s!=' "' ; s++, d++)
*d=*s;
*d=0 ;
current->text .push_back (text);
auto start = line.find (' \" ' );
if (start == std::string::npos)
return (subtitle_t *)ERR;
auto end = line.find (' \" ' , start + 1 );
if (end == std::string::npos)
return (subtitle_t *)ERR;
current->text .push_back (line.substr (start+1 , end));
return current;
}
static subtitle_t *sub_read_line_mpsub (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
float a = NAN;
float b = NAN;
do {
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return nullptr ;
} while (sscanf (line, " %f %f" , &a, &b) !=2 );
} while (sscanf (line. c_str () , " %f %f" , &a, &b) !=2 );
demuxstr->mpsub_position += (a*100 .0F );
current->start = (int ) demuxstr->mpsub_position ;
demuxstr->mpsub_position += (b*100 .0F );
current->end = (int ) demuxstr->mpsub_position ;
while (true ) {
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
return (current->text .size () > 0 ) ? current : nullptr ;
if (!read_line_from_input (demuxstr, line))
return (! current->text .empty () ) ? current : nullptr ;
char *p= line;
while ( isspace (*p) )
p++ ;
size_t mark = line. find_first_not_of ( " \t\r\n " ) ;
if (mark != std::string::npos )
line. erase ( 0 , mark) ;
if (eol (*p ) && current->text .size () > 0 )
if (eol (line[ 0 ] ) && ! current->text .empty () )
return current;
if (eol (*p ))
if (eol (line[ 0 ] ))
return nullptr ;
char *q = nullptr ;
for (q=p ; !eol (*q); q++);
for (q=line. data () ; !eol (*q); q++);
*q=' \0 ' ;
if (strlen (p)) {
current->text .push_back (p);
/* printf(">%s<\n",p); */
line.resize (strlen (line.c_str ()));
if (!line.empty ()) {
current->text .push_back (line);
/* printf(">%s<\n",line.data()); */
} else {
if (current->text .size ())
if (! current->text .empty ())
return current;
return nullptr ;
}
Expand All
@@ -602,28 +588,28 @@ static subtitle_t *sub_read_line_mpsub (demux_sputext_t *demuxstr, subtitle_t *c
}
static subtitle_t *sub_read_line_aqt (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
while (true ) {
/* try to locate next subtitle_t */
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return nullptr ;
if (!(sscanf (line, " -->> %ld" , &(current->start )) <1 ))
if (!(sscanf (line. c_str () , " -->> %ld" , &(current->start )) <1 ))
break ;
}
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return nullptr ;
std::string out {};
sub_readtext (( char *) &line ,out);
sub_readtext (line. data () ,out);
current->text .push_back (out);
current->end = -1 ;
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return current;;
sub_readtext (( char *) &line ,out);
sub_readtext (line. data () ,out);
current->text .push_back (out);
if ((current->text [0 ][0 ]==0 ) && (current->text [1 ][0 ]==0 )) {
Expand All
@@ -634,46 +620,44 @@ static subtitle_t *sub_read_line_aqt (demux_sputext_t *demuxstr, subtitle_t *cur
}
static subtitle_t *sub_read_line_jacobsub (demux_sputext_t *demuxstr, subtitle_t *current) {
char line1[LINE_LEN+ 1 ] ;
char line2[LINE_LEN+ 1 ] ;
char directive[ LINE_LEN+ 1 ] ;
std::string line1;
std::string line2;
std::string directive; directive. resize ( LINE_LEN) ;
char *p = nullptr ;
char *q = nullptr ;
unsigned a1=0 , a2=0 , a3=0 , a4=0 , b1=0 , b2=0 , b3=0 , b4=0 ; // NOLINT(readability-isolate-declaration)
unsigned comment = 0 ;
static unsigned s_jacoTimeRes = 30 ;
static int s_jacoShift = 0 ;
static uint32_t s_jacoTimeRes = 30 ;
static uint32_t s_jacoShift = 0 ;
memset (line1, 0 , LINE_LEN+1 );
memset (line2, 0 , LINE_LEN+1 );
memset (directive, 0 , LINE_LEN+1 );
while (current->text .empty ()) {
if (!read_line_from_input (demuxstr, line1, LINE_LEN )) {
if (!read_line_from_input (demuxstr, line1)) {
return nullptr ;
}
// Support continuation lines
if (strlen ( line1) >= 2 ) {
while ((line1[strlen ( line1)-2 ] == ' \\ ' ) && (line1[strlen ( line1)-1 ] == ' \n ' )) {
int newlen = strlen (line1)-2 ;
if (!read_line_from_input (demuxstr, line2, LINE_LEN - newlen ))
if (line1. size ( ) >= 2 ) {
while ((line1[line1. size ( )-2 ] == ' \\ ' ) && (line1[line1. size ( )-1 ] == ' \n ' )) {
line1. resize (line1. size ( )-2 ) ;
if (!read_line_from_input (demuxstr, line2))
return nullptr ;
p = line2;
while ((*p == ' ' ) || (*p == ' \t ' )) {
++p;
}
strcpy (line1+newlen, p);
size_t index = line2.find_first_not_of (" \t\r\n " );
if (index != std::string::npos)
line2.erase (0 , index );
line1 += line2;
}
}
line2.resize (0 );
line2.resize (LINE_LEN);
if (sscanf
(line1, " %u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT " [^\n\r ]" , &a1, &a2, &a3, &a4,
&b1, &b2, &b3, &b4, line2) < 9 ) {
if (sscanf (line1, " @%u @%u %" LINE_LEN_QUOT " [^\n\r ]" , &a4, &b4, line2) < 3 ) {
(line1. c_str () , " %u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT " [^\n\r ]" , &a1, &a2, &a3, &a4,
&b1, &b2, &b3, &b4, line2. data () ) < 9 ) {
if (sscanf (line1. data () , " @%u @%u %" LINE_LEN_QUOT " [^\n\r ]" , &a4, &b4, line2. data () ) < 3 ) {
if (line1[0 ] == ' #' ) {
int hours = 0 ;
int minutes = 0 ;
int seconds = 0 ;
int delta = 0 ;
unsigned units = s_jacoShift;
uint32_t units = s_jacoShift;
int inverter = 1 ;
switch (toupper (line1[1 ])) {
case ' S' :
Expand Down
Expand Up
@@ -739,38 +723,36 @@ static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *demuxstr, subtitle_t
long ) (((b1 * 3600 + b2 * 60 + b3) * s_jacoTimeRes + b4 +
s_jacoShift) * 100.0 / s_jacoTimeRes);
}
p = line2;
p = line2. data () ;
while ((*p == ' ' ) || (*p == ' \t ' )) {
++p;
}
if (isalpha (*p)||*p == ' [' ) {
if (sscanf (p, " %" LINE_LEN_QUOT " s %" LINE_LEN_QUOT " [^\n\r ]" , directive, line1) < 2 )
if (sscanf (p, " %" LINE_LEN_QUOT " s %" LINE_LEN_QUOT " [^\n\r ]" , directive. data () , line1. data () ) < 2 )
return (subtitle_t *)ERR;
int jLength = strlen (directive);
for (int cont = 0 ; cont < jLength; ++cont) {
if (isalpha (*(directive + cont)))
*(directive + cont) = toupper (*(directive + cont));
}
if ((strstr (directive, " RDB" ) != nullptr )
|| (strstr (directive, " RDC" ) != nullptr )
|| (strstr (directive, " RLB" ) != nullptr )
|| (strstr (directive, " RLG" ) != nullptr )) {
directive.resize (strlen (directive.c_str ()));
std::transform (directive.begin (), directive.end (), directive.begin (),
[](unsigned char c){ return std::toupper (c);});
if ( (directive.find (" RDB" ) != std::string::npos)
|| (directive.find (" RDC" ) != std::string::npos)
|| (directive.find (" RLB" ) != std::string::npos)
|| (directive.find (" RLG" ) != std::string::npos)) {
continue ;
}
/* no alignment */
#if 0
if (strstr( directive, "JL") != nullptr ) {
if (directive.find( "JL") != std::string::npos ) {
current->alignment = SUB_ALIGNMENT_HLEFT;
} else if (strstr( directive, "JR") != nullptr ) {
} else if (directive.find( "JR") != std::string::npos ) {
current->alignment = SUB_ALIGNMENT_HRIGHT;
} else {
current->alignment = SUB_ALIGNMENT_HCENTER;
}
#endif
strcpy ( line2, line1) ;
p = line2;
line2 = line1;
p = line2. data () ;
}
for (q = line1; (!eol (*p)); ++p) {
for (q = line1. data () ; (!eol (*p)); ++p) {
switch (*p) {
case ' {' :
comment++;
Expand Down
Expand Up
@@ -801,7 +783,7 @@ static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *demuxstr, subtitle_t
case ' \\ ' :
if (*(p + 1 ) == ' n' ) {
*q = ' \0 ' ;
q = line1;
q = line1. data () ;
current->text .push_back (line1);
++p;
break ;
Expand All
@@ -826,12 +808,14 @@ static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *demuxstr, subtitle_t
(*(p + 1 ) == ' ~' ) || (*(p + 1 ) == ' {' )) {
++p;
} else if (eol (*(p + 1 ))) {
if (!read_line_from_input (demuxstr, directive, LINE_LEN))
std::string tmpstr {};
if (!read_line_from_input (demuxstr, tmpstr))
return nullptr ;
trail_space (directive);
strncat (line2, directive,
((LINE_LEN > 511 ) ? LINE_LEN-1 : 511 )
- strlen (line2));
trail_space (tmpstr);
// The std::string addition can reallocate...
size_t offset = p - line2.data ();
line2 += tmpstr;
p = line2.data () + offset;
break ;
}
// Checked xine-lib-1.2.8. No fix there. Seems like it
Expand All
@@ -851,48 +835,44 @@ static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *demuxstr, subtitle_t
}
static subtitle_t *sub_read_line_subviewer2 (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN+ 1 ] ;
std::string line;
int a1=0 ,a2=0 ,a3=0 ,a4=0 ; // NOLINT(readability-isolate-declaration)
char *p=nullptr ;
while (current->text .empty ()) {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
if (!read_line_from_input (demuxstr, line)) return nullptr ;
if (line[0 ]!=' {' )
continue ;
if (sscanf (line, " {T %d:%d:%d:%d" ,&a1,&a2,&a3,&a4) < 4 )
if (sscanf (line. data () , " {T %d:%d:%d:%d" ,&a1,&a2,&a3,&a4) < 4 )
continue ;
current->start = a1*360000 +a2*6000 +a3*100 +a4/10 ;
for (;;) {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) break ;
if (!read_line_from_input (demuxstr, line)) break ;
if (line[0 ]==' }' ) break ;
int len=0 ;
for (p=line; *p!=' \n ' && *p!=' \r ' && *p; ++p,++len);
if (len) {
current->text .push_back (std::string (line, len));
} else {
size_t len = line.find_first_of (" \n\r " );
if (len == 0 )
break ;
}
current-> text . push_back (line. substr ( 0 , len));
}
}
return current;
}
static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN + 1 ] ;
std::string line;
int h = 0 ;
int m = 0 ;
int s = 0 ;
do {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
} while (sscanf (line, " [%d:%d:%d]" , &h, &m, &s) != 3 );
if (!read_line_from_input (demuxstr, line)) return nullptr ;
} while (sscanf (line. data () , " [%d:%d:%d]" , &h, &m, &s) != 3 );
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
if (!read_line_from_input (demuxstr, line)) return nullptr ;
current->start = 360000 * h + 6000 * m + 100 * s;
current->end = -1 ;
char *next=line;
char *next=line. data () ;
std::string out {};
while ((next = sub_readtext (next, out))) {
if (next==ERR) return (subtitle_t *)ERR;
Expand All
@@ -908,18 +888,18 @@ static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *demuxstr, subtitle_t
*/
static subtitle_t *sub_read_line_mpl2 (demux_sputext_t *demuxstr, subtitle_t *current) {
char line[LINE_LEN+ 1 ] ;
char line2[ LINE_LEN+ 1 ] ;
std::string line;
std::string line2; line2. resize ( LINE_LEN) ;
do {
if (!read_line_from_input (demuxstr, line, LINE_LEN )) return nullptr ;
} while ((sscanf (line,
if (!read_line_from_input (demuxstr, line)) return nullptr ;
} while ((sscanf (line. data () ,
" [%ld][%ld]%" LINE_LEN_QUOT " [^\r\n ]" ,
&(current->start ), &(current->end ), line2) < 3 ));
&(current->start ), &(current->end ), line2. data () ) < 3 ));
current->start *= 10 ;
current->end *= 10 ;
char *p=line2;
char *p=line2. data () ;
char *next=p;
std::string out {};
while ((next = sub_readtext (next, out))) {
Expand All
@@ -934,39 +914,41 @@ static subtitle_t *sub_read_line_mpl2(demux_sputext_t *demuxstr, subtitle_t *cur
static int sub_autodetect (demux_sputext_t *demuxstr) {
char line[LINE_LEN + 1 ];
char line2[LINE_LEN + 1 ];
std::string line;
int i = 0 ;
int j = 0 ;
char p = 0 ;
while (j < 100 ) {
j++;
if (!read_line_from_input (demuxstr, line, LINE_LEN ))
if (!read_line_from_input (demuxstr, line))
return FORMAT_UNKNOWN;
if ((sscanf (line, " {%d}{}" , &i)==1 ) ||
(sscanf (line, " {%d}{%d}" , &i, &i)==2 )) {
std::transform (line.begin (), line.end (), line.begin (),
[](unsigned char c){ return std::tolower (c);});
if ((sscanf (line.data (), " {%d}{}" , &i)==1 ) ||
(sscanf (line.data (), " {%d}{%d}" , &i, &i)==2 )) {
demuxstr->uses_time =0 ;
return FORMAT_MICRODVD;
}
if (sscanf (line, " %d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ) {
if (sscanf (line. data () , " %d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ) {
demuxstr->uses_time =1 ;
return FORMAT_SUBRIP;
}
if (sscanf (line, " %d:%d:%d.%d,%d:%d:%d.%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ){
if (sscanf (line. data () , " %d:%d:%d.%d,%d:%d:%d.%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ){
demuxstr->uses_time =1 ;
return FORMAT_SUBVIEWER;
}
if (sscanf (line, " %d:%d:%d,%d,%d:%d:%d,%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ){
if (sscanf (line. data () , " %d:%d:%d,%d,%d:%d:%d,%d" , &i, &i, &i, &i, &i, &i, &i, &i)==8 ){
demuxstr->uses_time =1 ;
return FORMAT_SUBVIEWER;
}
if (strstr ( line, " <SAMI >" )) {
if (line. find ( " <sami >" ) != std::string::npos ) {
demuxstr->uses_time =1 ;
return FORMAT_SAMI;
}
Expand All
@@ -975,54 +957,56 @@ static int sub_autodetect (demux_sputext_t *demuxstr) {
// seconds. Add a final "the rest of the line" argument to get
// that validation, so that JACO subtitles can be distinguished
// from this format.
if (sscanf (line, " %d:%d:%d:%" LINE_LEN_QUOT " [^\n\r ]" ,
&i, &i, &i, line2 )==4 ) {
std::string line2; line2.resize (LINE_LEN);
if (sscanf (line.data (), " %d:%d:%d:%" LINE_LEN_QUOT " [^\n\r ]" ,
&i, &i, &i, line2.data () )==4 ) {
demuxstr->uses_time =1 ;
return FORMAT_VPLAYER;
}
/*
* A RealText format is a markup language, starts with <window> tag,
* options (behaviour modifiers) are possible.
*/
if ( strncasecmp ( line, " <window" , 7 ) == 0 ) {
if (line. find ( " <window" ) != std::string::npos ) {
demuxstr->uses_time =1 ;
return FORMAT_RT;
}
if ((memcmp (line, " Dialogue: Marked" , 16 ) == 0 ) || (memcmp (line, " Dialogue: " , 10 ) == 0 )) {
if ((line.find (" dialogue: marked" ) != std::string::npos) ||
(line.find (" dialogue: " ) != std::string::npos)) {
demuxstr->uses_time =1 ;
return FORMAT_SSA;
}
if (sscanf (line, " %d,%d,\" %c" , &i, &i, (char *) &i) == 3 ) {
if (sscanf (line. data () , " %d,%d,\" %c" , &i, &i, (char *) &i) == 3 ) {
demuxstr->uses_time =0 ;
return FORMAT_PJS;
}
if (sscanf (line, " FORMAT =%d" , &i) == 1 ) {
if (sscanf (line. data () , " format =%d" , &i) == 1 ) {
demuxstr->uses_time =0 ;
return FORMAT_MPSUB;
}
if (sscanf (line, " FORMAT=TIM %c" , &p)==1 && p==' E ' ) {
if (sscanf (line. data () , " format=tim %c" , &p)==1 && p==' e ' ) {
demuxstr->uses_time =1 ;
return FORMAT_MPSUB;
}
if (strstr ( line, " -->>" )) {
if (line. find ( " -->>" ) != std::string::npos ) {
demuxstr->uses_time =0 ;
return FORMAT_AQTITLE;
}
if (sscanf (line, " @%d @%d" , &i, &i) == 2 ||
sscanf (line, " %d:%d:%d.%d %d:%d:%d.%d" , &i, &i, &i, &i, &i, &i, &i, &i) == 8 ) {
if (sscanf (line. data () , " @%d @%d" , &i, &i) == 2 ||
sscanf (line. data () , " %d:%d:%d.%d %d:%d:%d.%d" , &i, &i, &i, &i, &i, &i, &i, &i) == 8 ) {
demuxstr->uses_time = 1 ;
return FORMAT_JACOBSUB;
}
if (sscanf (line, " {T %d:%d:%d:%d" ,&i, &i, &i, &i) == 4 ) {
if (sscanf (line. data () , " {t %d:%d:%d:%d" ,&i, &i, &i, &i) == 4 ) {
demuxstr->uses_time = 1 ;
return FORMAT_SUBVIEWER2;
}
if (sscanf (line, " [%d:%d:%d]" , &i, &i, &i) == 3 ) {
if (sscanf (line. data () , " [%d:%d:%d]" , &i, &i, &i) == 3 ) {
demuxstr->uses_time = 1 ;
return FORMAT_SUBRIP09;
}
if (sscanf (line, " [%d][%d]" , &i, &i) == 2 ) {
if (sscanf (line. data () , " [%d][%d]" , &i, &i) == 2 ) {
demuxstr->uses_time = 1 ;
return FORMAT_MPL2;
}
Expand Down
Expand Up
@@ -1124,7 +1108,5 @@ bool sub_read_file (demux_sputext_t *demuxstr) {
}
#endif
// No memory leak of 'sub' here. 'Sub' always points to an element in 'first'.
// NOLINT(clang-analyzer-unix.Malloc)
return true ;
}