Bug 849189 - Update webvtt to recent upstream version. r=rillian

This commit is contained in:
Jacek Caban 2013-03-08 03:47:00 -08:00
Родитель d81b1e261e
Коммит 8523227c6b
18 изменённых файлов: 1016 добавлений и 509 удалений

Просмотреть файл

@ -22,6 +22,7 @@ DEFINES += \
EXPORTS_webvtt = \
include/webvtt/cue.h \
include/webvtt/error.h \
include/webvtt/node.h \
include/webvtt/parser.h \
include/webvtt/string.h \
include/webvtt/util.h \
@ -33,6 +34,7 @@ CSRCS = \
cuetext.c \
error.c \
lexer.c \
node.c \
parser.c \
string.c \
$(NULL)

Просмотреть файл

@ -1,5 +1,5 @@
These files are from the WebVTT library, and are extracted from rev
cd5e95654f1fd6712fcf1941f8936870a484f65e of the git repository at
6b637c9f30911433e6d5a5be5d8512317a0d8a14 of the git repository at
https://github.com/mozilla/webvtt.
The following CPPFLAGS are used in order to build and link in Mozilla

Просмотреть файл

@ -26,11 +26,7 @@
*/
#include <webvtt/util.h>
#if ( defined(__APPLE__) && defined(__MACH__) )
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include <string.h>
static void *default_alloc( void *unused, webvtt_uint nb );

Просмотреть файл

@ -25,8 +25,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "parser_internal.h"
#include "cue_internal.h"
@ -117,191 +115,3 @@ webvtt_validate_cue( webvtt_cue *cue )
error:
return 0;
}
static webvtt_node empty_node = {
{ 1 }, /* init ref count */
0, /* parent */
WEBVTT_EMPTY_NODE /* node kind */
};
WEBVTT_EXPORT void
webvtt_ref_node( webvtt_node *node )
{
if( node ) {
webvtt_ref( &node->refs );
}
}
WEBVTT_EXPORT void
webvtt_init_node( webvtt_node **node )
{
if( *node != &empty_node ) {
if( node && *node ) {
webvtt_release_node( node );
}
*node = &empty_node;
webvtt_ref_node( *node );
}
}
WEBVTT_INTERN webvtt_status
webvtt_create_node( webvtt_node **node, webvtt_node_kind kind, webvtt_node *parent )
{
webvtt_node *temp_node;
if( !node ) {
return WEBVTT_INVALID_PARAM;
}
if( !( temp_node = (webvtt_node *)webvtt_alloc0(sizeof(*temp_node)) ) )
{
return WEBVTT_OUT_OF_MEMORY;
}
webvtt_ref_node( temp_node );
temp_node->kind = kind;
temp_node->parent = parent;
*node = temp_node;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_internal_node( webvtt_node **node, webvtt_node *parent, webvtt_node_kind kind,
webvtt_stringlist *css_classes, webvtt_string *annotation )
{
webvtt_status status;
webvtt_internal_node_data *node_data;
if( WEBVTT_FAILED( status = webvtt_create_node( node, kind, parent ) ) ) {
return status;
}
if ( !( node_data = (webvtt_internal_node_data *)webvtt_alloc0( sizeof(*node_data) ) ) )
{
return WEBVTT_OUT_OF_MEMORY;
}
webvtt_copy_stringlist( &node_data->css_classes, css_classes );
webvtt_copy_string( &node_data->annotation, annotation );
node_data->children = NULL;
node_data->length = 0;
node_data->alloc = 0;
(*node)->data.internal_data = node_data;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_head_node( webvtt_node **node )
{
webvtt_status status;
webvtt_string temp_annotation;
webvtt_init_string( &temp_annotation );
if( WEBVTT_FAILED( status = webvtt_create_internal_node( node, NULL, WEBVTT_HEAD_NODE, NULL, &temp_annotation ) ) ) {
return status;
}
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_time_stamp_leaf_node( webvtt_node **node, webvtt_node *parent, webvtt_timestamp time_stamp )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_node( node, WEBVTT_TIME_STAMP, parent ) ) ) {
return status;
}
(*node)->data.timestamp = time_stamp;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_text_leaf_node( webvtt_node **node, webvtt_node *parent, webvtt_string *text )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_node( node, WEBVTT_TEXT, parent ) ) ) {
return status;
}
webvtt_copy_string( &(*node)->data.text, text );
return WEBVTT_SUCCESS;
}
WEBVTT_EXPORT void
webvtt_release_node( webvtt_node **node )
{
webvtt_uint i;
webvtt_node *n;
if( !node || !*node ) {
return;
}
n = *node;
if( webvtt_deref( &n->refs ) == 0 ) {
if( n->kind == WEBVTT_TEXT ) {
webvtt_release_string( &n->data.text );
} else if( WEBVTT_IS_VALID_INTERNAL_NODE( n->kind ) && n->data.internal_data ) {
webvtt_release_stringlist( &n->data.internal_data->css_classes );
webvtt_release_string( &n->data.internal_data->annotation );
for( i = 0; i < n->data.internal_data->length; i++ ) {
webvtt_release_node( n->data.internal_data->children + i );
}
webvtt_free( n->data.internal_data->children );
webvtt_free( n->data.internal_data );
}
webvtt_free( n );
}
*node = 0;
}
WEBVTT_INTERN webvtt_status
webvtt_attach_internal_node( webvtt_node *parent, webvtt_node *to_attach )
{
webvtt_node **next = 0;
webvtt_internal_node_data *nd = 0;
if( !parent || !to_attach || !parent->data.internal_data ) {
return WEBVTT_INVALID_PARAM;
}
nd = parent->data.internal_data;
if( nd->alloc == 0 ) {
next = (webvtt_node **)webvtt_alloc0( sizeof( webvtt_node * ) * 8 );
if( !next ) {
return WEBVTT_OUT_OF_MEMORY;
}
nd->children = next;
nd->alloc = 8;
}
if( nd->length + 1 >= ( nd->alloc / 3 ) * 2 ) {
next = (webvtt_node **)webvtt_alloc0( sizeof( *next ) * nd->alloc * 2 );
if( !next ) {
return WEBVTT_OUT_OF_MEMORY;
}
nd->alloc *= 2;
memcpy( next, nd->children, nd->length * sizeof( webvtt_node * ) );
webvtt_free( nd->children );
nd->children = next;
}
nd->children[ nd->length++ ] = to_attach;
webvtt_ref_node( to_attach );
return WEBVTT_SUCCESS;
}

Просмотреть файл

@ -27,27 +27,8 @@
#ifndef __INTERN_CUE_H__
# define __INTERN_CUE_H__
# include <webvtt/string.h>
# include <webvtt/cue.h>
/**
* Routines for creating nodes.
*/
WEBVTT_INTERN webvtt_status webvtt_create_node( webvtt_node **node, webvtt_node_kind kind, webvtt_node *parent );
WEBVTT_INTERN webvtt_status webvtt_create_internal_node( webvtt_node **node, webvtt_node *parent, webvtt_node_kind kind, webvtt_stringlist *css_classes, webvtt_string *annotation );
/**
* We probably shouldn't have a 'head node' type.
* We should just return a list of node trees...
*/
WEBVTT_INTERN webvtt_status webvtt_create_head_node( webvtt_node **node );
WEBVTT_INTERN webvtt_status webvtt_create_time_stamp_leaf_node( webvtt_node **node, webvtt_node *parent, webvtt_timestamp time_stamp );
WEBVTT_INTERN webvtt_status webvtt_create_text_leaf_node( webvtt_node **node, webvtt_node *parent, webvtt_string *text );
/**
* Attaches a node to the internal node list of another node.
*/
WEBVTT_INTERN webvtt_status webvtt_attach_internal_node( webvtt_node *parent, webvtt_node *to_attach );
/**
* Private cue flags
*/
@ -63,6 +44,12 @@ enum {
CUE_HAVE_CUEPARAMS = 0x40000000,
CUE_HAVE_ID = 0x80000000,
CUE_HEADER_MASK = CUE_HAVE_CUEPARAMS|CUE_HAVE_ID,
};
static webvtt_bool
cue_is_incomplete( const webvtt_cue *cue ) {
return !cue || ( cue->flags & CUE_HEADER_MASK ) == CUE_HAVE_ID;
}
#endif

Просмотреть файл

@ -81,7 +81,7 @@ webvtt_skipwhite( webvtt_byte **position )
}
WEBVTT_INTERN webvtt_status
webvtt_create_cuetext_token( webvtt_cuetext_token **token, webvtt_cuetext_token_type token_type )
webvtt_create_token( webvtt_cuetext_token **token, webvtt_token_type token_type )
{
webvtt_cuetext_token *temp_token = (webvtt_cuetext_token *)webvtt_alloc0( sizeof(*temp_token) );
@ -96,13 +96,13 @@ webvtt_create_cuetext_token( webvtt_cuetext_token **token, webvtt_cuetext_token_
}
WEBVTT_INTERN webvtt_status
webvtt_create_cuetext_start_token( webvtt_cuetext_token **token, webvtt_string *tag_name,
webvtt_create_start_token( webvtt_cuetext_token **token, webvtt_string *tag_name,
webvtt_stringlist *css_classes, webvtt_string *annotation )
{
webvtt_status status;
webvtt_cuetext_start_token_data sd;
webvtt_start_token_data sd;
if( WEBVTT_FAILED( status = webvtt_create_cuetext_token( token, START_TOKEN ) ) ) {
if( WEBVTT_FAILED( status = webvtt_create_token( token, START_TOKEN ) ) ) {
return status;
}
@ -116,11 +116,11 @@ webvtt_create_cuetext_start_token( webvtt_cuetext_token **token, webvtt_string *
}
WEBVTT_INTERN webvtt_status
webvtt_create_cuetext_end_token( webvtt_cuetext_token **token, webvtt_string *tag_name )
webvtt_create_end_token( webvtt_cuetext_token **token, webvtt_string *tag_name )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_cuetext_token( token, END_TOKEN ) ) ) {
if( WEBVTT_FAILED( status = webvtt_create_token( token, END_TOKEN ) ) ) {
return status;
}
@ -130,11 +130,11 @@ webvtt_create_cuetext_end_token( webvtt_cuetext_token **token, webvtt_string *ta
}
WEBVTT_INTERN webvtt_status
webvtt_create_cuetext_text_token( webvtt_cuetext_token **token, webvtt_string *text )
webvtt_create_text_token( webvtt_cuetext_token **token, webvtt_string *text )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_cuetext_token( token, TEXT_TOKEN ) ) ) {
if( WEBVTT_FAILED( status = webvtt_create_token( token, TEXT_TOKEN ) ) ) {
return status;
}
@ -144,11 +144,11 @@ webvtt_create_cuetext_text_token( webvtt_cuetext_token **token, webvtt_string *t
}
WEBVTT_INTERN webvtt_status
webvtt_create_cuetext_timestamp_token( webvtt_cuetext_token **token, webvtt_timestamp time_stamp )
webvtt_create_timestamp_token( webvtt_cuetext_token **token, webvtt_timestamp time_stamp )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_cuetext_token( token, TIME_STAMP_TOKEN ) ) ) {
if( WEBVTT_FAILED( status = webvtt_create_token( token, TIME_STAMP_TOKEN ) ) ) {
return status;
}
@ -158,9 +158,9 @@ webvtt_create_cuetext_timestamp_token( webvtt_cuetext_token **token, webvtt_time
}
WEBVTT_INTERN void
webvtt_delete_cuetext_token( webvtt_cuetext_token **token )
webvtt_delete_token( webvtt_cuetext_token **token )
{
webvtt_cuetext_start_token_data data;
webvtt_start_token_data data;
webvtt_cuetext_token *t;
if( !token ) {
@ -193,31 +193,14 @@ webvtt_delete_cuetext_token( webvtt_cuetext_token **token )
*token = 0;
}
/**
* Definitions for tag names that accept annotationsm
*/
#define V_TAG_LENGTH 1
webvtt_byte v_tag[V_TAG_LENGTH] = { UTF8_V };
WEBVTT_INTERN int
tag_accepts_annotation( webvtt_string *tag_name )
{
return memcmp( webvtt_string_text( tag_name ), v_tag,
min(webvtt_string_length( tag_name ), V_TAG_LENGTH) ) == 0;
return webvtt_string_is_equal( tag_name, "v", 1 );
}
/**
* Definitions for tag tokens that are more then one character long.
*/
#define RUBY_TAG_LENGTH 4
#define RUBY_TEXT_TAG_LENGTH 2
webvtt_byte ruby_tag[RUBY_TAG_LENGTH] = { UTF8_R, UTF8_U, UTF8_B, UTF8_Y };
webvtt_byte rt_tag[RUBY_TEXT_TAG_LENGTH] = { UTF8_R, UTF8_T };
WEBVTT_INTERN webvtt_status
webvtt_get_node_kind_from_tag_name( webvtt_string *tag_name, webvtt_node_kind *kind )
webvtt_node_kind_from_tag_name( webvtt_string *tag_name, webvtt_node_kind *kind )
{
if( !tag_name || !kind ) {
return WEBVTT_INVALID_PARAM;
@ -241,9 +224,9 @@ webvtt_get_node_kind_from_tag_name( webvtt_string *tag_name, webvtt_node_kind *k
*kind = WEBVTT_VOICE;
break;
}
} else if( memcmp( webvtt_string_text(tag_name), ruby_tag, min(webvtt_string_length(tag_name), RUBY_TAG_LENGTH) ) == 0 ) {
} else if( webvtt_string_is_equal( tag_name, "ruby", 4 ) ) {
*kind = WEBVTT_RUBY;
} else if( memcmp( webvtt_string_text(tag_name), rt_tag, min(webvtt_string_length(tag_name), RUBY_TEXT_TAG_LENGTH) ) == 0 ) {
} else if( webvtt_string_is_equal( tag_name, "rt", 2 ) ) {
*kind = WEBVTT_RUBY_TEXT;
} else {
return WEBVTT_INVALID_TAG_NAME;
@ -272,18 +255,18 @@ webvtt_create_node_from_token( webvtt_cuetext_token *token, webvtt_node **node,
switch ( token->token_type ) {
case( TEXT_TOKEN ):
return webvtt_create_text_leaf_node( node, parent, &token->text );
return webvtt_create_text_node( node, parent, &token->text );
break;
case( START_TOKEN ):
CHECK_MEMORY_OP( webvtt_get_node_kind_from_tag_name( &token->tag_name, &kind) );
CHECK_MEMORY_OP( webvtt_node_kind_from_tag_name( &token->tag_name, &kind) );
return webvtt_create_internal_node( node, parent, kind,
token->start_token_data.css_classes, &token->start_token_data.annotations );
break;
case ( TIME_STAMP_TOKEN ):
return webvtt_create_time_stamp_leaf_node( node, parent, token->time_stamp );
return webvtt_create_timestamp_node( node, parent, token->time_stamp );
break;
default:
return WEBVTT_INVALID_TOKEN_TYPE;
@ -291,8 +274,8 @@ webvtt_create_node_from_token( webvtt_cuetext_token *token, webvtt_node **node,
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_data_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_data_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
for ( ; *token_state == DATA; (*position)++ ) {
switch( **position ) {
@ -319,26 +302,12 @@ webvtt_cuetext_tokenizer_data_state( webvtt_byte **position,
}
/**
* Definitions for valid escape values.
* The semicolon is implicit in the comparison.
* Definitions for escape sequence replacement strings.
*/
#define AMP_ESCAPE_LENGTH 4
#define LT_ESCAPE_LENGTH 3
#define GT_ESCAPE_LENGTH 3
#define RLM_ESCAPE_LENGTH 4
#define LRM_ESCAPE_LENGTH 4
#define NBSP_ESCAPE_LENGTH 5
#define RLM_REPLACE_LENGTH 3
#define LRM_REPLACE_LENGTH 3
#define NBSP_REPLACE_LENGTH 2
webvtt_byte amp_escape[AMP_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_A, UTF8_M, UTF8_P };
webvtt_byte lt_escape[LT_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_L, UTF8_T };
webvtt_byte gt_escape[GT_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_G, UTF8_T };
webvtt_byte rlm_escape[RLM_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_R, UTF8_L, UTF8_M };
webvtt_byte lrm_escape[LRM_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_L, UTF8_R, UTF8_M };
webvtt_byte nbsp_escape[NBSP_ESCAPE_LENGTH] = { UTF8_AMPERSAND, UTF8_N, UTF8_B, UTF8_S, UTF8_P };
webvtt_byte rlm_replace[RLM_REPLACE_LENGTH] = { UTF8_RIGHT_TO_LEFT_1,
UTF8_RIGHT_TO_LEFT_2, UTF8_RIGHT_TO_LEFT_3 };
webvtt_byte lrm_replace[LRM_REPLACE_LENGTH] = { UTF8_LEFT_TO_RIGHT_1,
@ -347,8 +316,8 @@ webvtt_byte nbsp_replace[NBSP_REPLACE_LENGTH] = { UTF8_NO_BREAK_SPACE_1,
UTF8_NO_BREAK_SPACE_2 };
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_escape_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_escape_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
webvtt_string buffer;
webvtt_status status = WEBVTT_SUCCESS;
@ -387,17 +356,17 @@ webvtt_cuetext_tokenizer_escape_state( webvtt_byte **position,
* the interpretation to result and change the state to DATA.
*/
else if( **position == UTF8_SEMI_COLON ) {
if( memcmp( webvtt_string_text(&buffer), amp_escape, min(webvtt_string_length(&buffer), AMP_ESCAPE_LENGTH ) ) == 0 ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, UTF8_AMPERSAND ) );
} else if( memcmp( webvtt_string_text(&buffer), lt_escape, min(webvtt_string_length(&buffer), LT_ESCAPE_LENGTH ) ) == 0 ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, UTF8_LESS_THAN ) );
} else if( memcmp( webvtt_string_text(&buffer), gt_escape, min(webvtt_string_length(&buffer), GT_ESCAPE_LENGTH) ) == 0 ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, UTF8_GREATER_THAN ) );
} else if( memcmp( webvtt_string_text(&buffer), rlm_escape, min(webvtt_string_length(&buffer), RLM_ESCAPE_LENGTH) ) == 0 ) {
if( webvtt_string_is_equal( &buffer, "&amp", 4 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, '&' ) );
} else if( webvtt_string_is_equal( &buffer, "&lt", 3 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, '<' ) );
} else if( webvtt_string_is_equal( &buffer, "&gt", 3 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, '>' ) );
} else if( webvtt_string_is_equal( &buffer, "&rlm", 4 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_append( result, rlm_replace, RLM_REPLACE_LENGTH ) );
} else if( memcmp( webvtt_string_text(&buffer), lrm_escape, min(webvtt_string_length(&buffer), LRM_ESCAPE_LENGTH) ) == 0 ) {
} else if( webvtt_string_is_equal( &buffer, "&lrm", 4 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_append( result, lrm_replace, LRM_REPLACE_LENGTH ) );
} else if( memcmp( webvtt_string_text(&buffer), nbsp_escape, min(webvtt_string_length(&buffer), NBSP_ESCAPE_LENGTH) ) == 0 ) {
} else if( webvtt_string_is_equal( &buffer, "&nbsp", 5 ) ) {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_append( result, nbsp_replace, NBSP_REPLACE_LENGTH ) );
} else {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_append_string( result, &buffer ) );
@ -405,6 +374,7 @@ webvtt_cuetext_tokenizer_escape_state( webvtt_byte **position,
}
*token_state = DATA;
status = WEBVTT_UNFINISHED;
}
/**
* Character is alphanumeric. This means we are in the body of the escape
@ -421,6 +391,7 @@ webvtt_cuetext_tokenizer_escape_state( webvtt_byte **position,
else {
CHECK_MEMORY_OP_JUMP( status, webvtt_string_append_string( result, &buffer ) );
CHECK_MEMORY_OP_JUMP( status, webvtt_string_putc( result, **position ) );
status = WEBVTT_UNFINISHED;
*token_state = DATA;
}
}
@ -432,8 +403,8 @@ dealloc:
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_tag_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
for( ; *token_state == TAG; (*position)++ ) {
if( **position == UTF8_TAB || **position == UTF8_LINE_FEED ||
@ -468,8 +439,8 @@ webvtt_cuetext_tokenizer_tag_state( webvtt_byte **position,
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_start_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_start_tag_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
for( ; *token_state == START_TAG; (*position)++ ) {
if( **position == UTF8_TAB || **position == UTF8_FORM_FEED ||
@ -498,8 +469,8 @@ webvtt_cuetext_tokenizer_start_tag_state( webvtt_byte **position,
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_start_tag_class_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_stringlist *css_classes )
webvtt_class_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_stringlist *css_classes )
{
webvtt_string buffer;
webvtt_status status = WEBVTT_SUCCESS;
@ -533,8 +504,8 @@ dealloc:
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_start_tag_annotation_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *annotation )
webvtt_annotation_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *annotation )
{
for( ; *token_state == START_TAG_ANNOTATION; (*position)++ ) {
if( **position == UTF8_NULL_BYTE || **position == UTF8_GREATER_THAN ) {
@ -547,8 +518,8 @@ webvtt_cuetext_tokenizer_start_tag_annotation_state( webvtt_byte **position,
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_end_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_end_tag_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
for( ; *token_state == END_TAG; (*position)++ ) {
if( **position == UTF8_GREATER_THAN || **position == UTF8_NULL_BYTE ) {
@ -561,8 +532,8 @@ webvtt_cuetext_tokenizer_end_tag_state( webvtt_byte **position,
}
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer_time_stamp_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result )
webvtt_timestamp_state( webvtt_byte **position, webvtt_token_state *token_state,
webvtt_string *result )
{
for( ; *token_state == TIME_STAMP_TAG; (*position)++ ) {
if( **position == UTF8_GREATER_THAN || **position == UTF8_NULL_BYTE ) {
@ -581,7 +552,7 @@ webvtt_cuetext_tokenizer_time_stamp_tag_state( webvtt_byte **position,
WEBVTT_INTERN webvtt_status
webvtt_cuetext_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token )
{
webvtt_cuetext_token_state token_state = DATA;
webvtt_token_state token_state = DATA;
webvtt_string result, annotation;
webvtt_stringlist *css_classes;
webvtt_timestamp time_stamp = 0;
@ -604,28 +575,28 @@ webvtt_cuetext_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token )
while( status == WEBVTT_UNFINISHED ) {
switch( token_state ) {
case DATA :
status = webvtt_cuetext_tokenizer_data_state( position, &token_state, &result );
status = webvtt_data_state( position, &token_state, &result );
break;
case ESCAPE:
status = webvtt_cuetext_tokenizer_escape_state( position, &token_state, &result );
status = webvtt_escape_state( position, &token_state, &result );
break;
case TAG:
status = webvtt_cuetext_tokenizer_tag_state( position, &token_state, &result );
status = webvtt_tag_state( position, &token_state, &result );
break;
case START_TAG:
status = webvtt_cuetext_tokenizer_start_tag_state( position, &token_state, &result );
status = webvtt_start_tag_state( position, &token_state, &result );
break;
case START_TAG_CLASS:
status = webvtt_cuetext_tokenizer_start_tag_class_state( position, &token_state, css_classes );
status = webvtt_class_state( position, &token_state, css_classes );
break;
case START_TAG_ANNOTATION:
status = webvtt_cuetext_tokenizer_start_tag_annotation_state( position, &token_state, &annotation );
status = webvtt_annotation_state( position, &token_state, &annotation );
break;
case END_TAG:
status = webvtt_cuetext_tokenizer_end_tag_state( position, &token_state, &result );
status = webvtt_end_tag_state( position, &token_state, &result );
break;
case TIME_STAMP_TAG:
status = webvtt_cuetext_tokenizer_time_stamp_tag_state( position, &token_state, &result );
status = webvtt_timestamp_state( position, &token_state, &result );
break;
}
@ -643,7 +614,7 @@ webvtt_cuetext_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token )
* needs to be made.
*/
if( token_state == DATA || token_state == ESCAPE ) {
status = webvtt_create_cuetext_text_token( token, &result );
status = webvtt_create_text_token( token, &result );
} else if(token_state == TAG || token_state == START_TAG || token_state == START_TAG_CLASS ||
token_state == START_TAG_ANNOTATION) {
/**
@ -654,12 +625,12 @@ webvtt_cuetext_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token )
webvtt_release_string( &annotation );
webvtt_init_string( &annotation );
}
status = webvtt_create_cuetext_start_token( token, &result, css_classes, &annotation );
status = webvtt_create_start_token( token, &result, css_classes, &annotation );
} else if( token_state == END_TAG ) {
status = webvtt_create_cuetext_end_token( token, &result );
status = webvtt_create_end_token( token, &result );
} else if( token_state == TIME_STAMP_TAG ) {
parse_timestamp( webvtt_string_text( &result ), &time_stamp );
status = webvtt_create_cuetext_timestamp_token( token, time_stamp );
status = webvtt_create_timestamp_token( token, time_stamp );
} else {
status = WEBVTT_INVALID_TOKEN_STATE;
}
@ -716,7 +687,7 @@ webvtt_parse_cuetext( webvtt_parser self, webvtt_cue *cue, webvtt_string *payloa
*/
while( *position != UTF8_NULL_BYTE ) {
webvtt_delete_cuetext_token( &token );
webvtt_delete_token( &token );
/* Step 7. */
switch( webvtt_cuetext_tokenizer( &position, &token ) ) {
@ -745,7 +716,7 @@ webvtt_parse_cuetext( webvtt_parser self, webvtt_cue *cue, webvtt_string *payloa
* We have encountered an end token but it is not in a format that is
* supported, throw away the token.
*/
if( webvtt_get_node_kind_from_tag_name( &token->tag_name, &kind ) == WEBVTT_INVALID_TAG_NAME ) {
if( webvtt_node_kind_from_tag_name( &token->tag_name, &kind ) == WEBVTT_INVALID_TAG_NAME ) {
continue;
}
@ -769,7 +740,7 @@ webvtt_parse_cuetext( webvtt_parser self, webvtt_cue *cue, webvtt_string *payloa
/* Do something here? */
}
else {
webvtt_attach_internal_node( current_node, temp_node );
webvtt_attach_node( current_node, temp_node );
if( WEBVTT_IS_VALID_INTERNAL_NODE( temp_node->kind ) ) {
current_node = temp_node;
@ -784,7 +755,7 @@ webvtt_parse_cuetext( webvtt_parser self, webvtt_cue *cue, webvtt_string *payloa
webvtt_skipwhite( &position );
}
webvtt_delete_cuetext_token( &token );
webvtt_delete_token( &token );
return WEBVTT_SUCCESS;
}

Просмотреть файл

@ -31,17 +31,17 @@
# include <webvtt/string.h>
# include <webvtt/cue.h>
typedef enum webvtt_cuetext_token_type_t webvtt_cuetext_token_type;
typedef enum webvtt_cuetext_token_state_t webvtt_cuetext_token_state;
typedef enum webvtt_token_type_t webvtt_token_type;
typedef enum webvtt_token_state_t webvtt_token_state;
typedef struct webvtt_cuetext_token_t webvtt_cuetext_token;
typedef struct webvtt_cuetext_start_token_data_t webvtt_cuetext_start_token_data;
typedef struct webvtt_start_token_data_t webvtt_start_token_data;
/**
* Enumerates token types.
*/
enum
webvtt_cuetext_token_type_t {
webvtt_token_type_t {
START_TOKEN, /* Identifies a webvtt_cue_text_start_tag_token. */
END_TOKEN, /* Identifies a webvtt_cue_text_end_tag_token. */
TIME_STAMP_TOKEN, /* Identifies a webvtt_cue_text_time_stamp_token. */
@ -52,7 +52,7 @@ webvtt_cuetext_token_type_t {
* Enumerates possible states that the cue text tokenizer can be in.
*/
enum
webvtt_cuetext_token_state_t {
webvtt_token_state_t {
DATA, /* Initial state. */
ESCAPE, /* Parsing an escape value. */
TAG, /* Reached a '<' character, about to start parsing a tag. */
@ -75,7 +75,7 @@ webvtt_cuetext_token_state_t {
* cue text.
*/
struct
webvtt_cuetext_start_token_data_t {
webvtt_start_token_data_t {
webvtt_stringlist *css_classes;
webvtt_string annotations;
};
@ -86,12 +86,12 @@ webvtt_cuetext_start_token_data_t {
*/
struct
webvtt_cuetext_token_t {
webvtt_cuetext_token_type token_type;
webvtt_token_type token_type;
webvtt_string tag_name; // Only used for start token and end token types.
union {
webvtt_string text;
webvtt_timestamp time_stamp;
webvtt_cuetext_start_token_data start_token_data;
webvtt_start_token_data start_token_data;
};
};
@ -99,12 +99,12 @@ webvtt_cuetext_token_t {
* Routines for creating cue text tokens.
* Sets the passed token to the new token.
*/
WEBVTT_INTERN webvtt_status webvtt_create_cuetext_token( webvtt_cuetext_token **token, webvtt_cuetext_token_type token_type );
WEBVTT_INTERN webvtt_status webvtt_create_cuetext_start_token( webvtt_cuetext_token **token, webvtt_string *tag_name,
WEBVTT_INTERN webvtt_status webvtt_create_token( webvtt_cuetext_token **token, webvtt_token_type token_type );
WEBVTT_INTERN webvtt_status webvtt_create_start_token( webvtt_cuetext_token **token, webvtt_string *tag_name,
webvtt_stringlist *css_classes, webvtt_string *annotation );
WEBVTT_INTERN webvtt_status webvtt_create_cuetext_end_token( webvtt_cuetext_token **token, webvtt_string *tag_name );
WEBVTT_INTERN webvtt_status webvtt_create_cuetext_text_token( webvtt_cuetext_token **token, webvtt_string *text );
WEBVTT_INTERN webvtt_status webvtt_create_cuetext_timestamp_token( webvtt_cuetext_token **token,
WEBVTT_INTERN webvtt_status webvtt_create_end_token( webvtt_cuetext_token **token, webvtt_string *tag_name );
WEBVTT_INTERN webvtt_status webvtt_create_text_token( webvtt_cuetext_token **token, webvtt_string *text );
WEBVTT_INTERN webvtt_status webvtt_create_timestamp_token( webvtt_cuetext_token **token,
webvtt_timestamp time_stamp );
/**
@ -115,14 +115,14 @@ WEBVTT_INTERN int tag_accepts_annotation( webvtt_string *tag_name );
/**
* Routines for deleting cue text tokens.
*/
WEBVTT_INTERN void webvtt_delete_cuetext_token( webvtt_cuetext_token **token );
WEBVTT_INTERN void webvtt_delete_token( webvtt_cuetext_token **token );
/**
* Converts the textual representation of a node kind into a particular kind.
* I.E. tag_name of 'ruby' would create a ruby kind, etc.
* Returns a WEBVTT_NOT_SUPPORTED if it does not find a valid tag name.
*/
WEBVTT_INTERN webvtt_status webvtt_get_node_kind_from_tag_name( webvtt_string *tag_name, webvtt_node_kind *kind );
WEBVTT_INTERN webvtt_status webvtt_node_kind_from_tag_name( webvtt_string *tag_name, webvtt_node_kind *kind );
/**
* Creates a node from a valid token.
@ -135,7 +135,7 @@ WEBVTT_INTERN webvtt_status webvtt_create_node_from_token( webvtt_cuetext_token
* cue text parser.
* Referenced from - http://dev.w3.org/html5/webvtt/#webvtt-cue-text-tokenizer
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token );
WEBVTT_INTERN webvtt_status webvtt_tokenizer( webvtt_byte **position, webvtt_cuetext_token **token );
/**
* Routines that take care of certain states in the webvtt cue text tokenizer.
@ -144,51 +144,51 @@ WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer( webvtt_byte **position, we
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-data-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_data_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_data_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-escape-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_escape_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_escape_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-tag-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_tag_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-start-tag-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_start_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_start_tag_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-start-tag-class-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_start_tag_class_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_stringlist *css_classes );
WEBVTT_INTERN webvtt_status webvtt_class_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_stringlist *css_classes );
/**
* Referenced from
* http://dev.w3.org/html5/webvtt/#webvtt-start-tag-annotation-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_start_tag_annotation_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *annotation );
WEBVTT_INTERN webvtt_status webvtt_annotation_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *annotation );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-end-tag-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_end_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_end_tag_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
/**
* Referenced from http://dev.w3.org/html5/webvtt/#webvtt-timestamp-tag-state
*/
WEBVTT_INTERN webvtt_status webvtt_cuetext_tokenizer_time_stamp_tag_state( webvtt_byte **position,
webvtt_cuetext_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_timestamp_state( webvtt_byte **position,
webvtt_token_state *token_state, webvtt_string *result );
WEBVTT_INTERN webvtt_status webvtt_parse_cuetext( webvtt_parser self, webvtt_cue *cue, webvtt_string *payload, int finished );

Просмотреть файл

@ -66,10 +66,10 @@ static const char *errstr[] = {
* (This might be too much work!)
*/
WEBVTT_EXPORT const char *
webvtt_strerror( webvtt_error errno )
webvtt_strerror( webvtt_error err )
{
if( errno >= (sizeof(errstr) / sizeof(*errstr)) ) {
if( err >= (sizeof(errstr) / sizeof(*errstr)) ) {
return "";
}
return errstr[ errno ];
return errstr[ err ];
}

Просмотреть файл

@ -29,6 +29,7 @@
# define __WEBVTT_CUE_H__
# include "util.h"
# include <webvtt/string.h>
# include <webvtt/node.h>
#if defined(__cplusplus) || defined(c_plusplus)
#define WEBVTT_CPLUSPLUS 1
@ -37,68 +38,6 @@ extern "C" {
#define WEBVTT_AUTO (0xFFFFFFFF)
typedef enum
webvtt_node_kind_t {
WEBVTT_NODE_LEAF = 0x80000000,
WEBVTT_NODE_INTERNAL = 0x00000000,
/**
* Internal Node objects
*/
WEBVTT_NODE_INTERNAL_START = 0,
WEBVTT_CLASS = 0 | WEBVTT_NODE_INTERNAL,
WEBVTT_ITALIC = 1 | WEBVTT_NODE_INTERNAL,
WEBVTT_BOLD = 2 | WEBVTT_NODE_INTERNAL,
WEBVTT_UNDERLINE = 3 | WEBVTT_NODE_INTERNAL,
WEBVTT_RUBY = 4 | WEBVTT_NODE_INTERNAL,
WEBVTT_RUBY_TEXT = 5 | WEBVTT_NODE_INTERNAL,
WEBVTT_VOICE = 6 | WEBVTT_NODE_INTERNAL,
/**
* This type of node has should not be rendered.
* It is the top of the node list and only contains a list of nodes.
*/
WEBVTT_HEAD_NODE = 7,
WEBVTT_NODE_INTERNAL_END = 7,
/**
* Leaf Node objects
*/
WEBVTT_NODE_LEAF_START = 256,
WEBVTT_TEXT = 256 | WEBVTT_NODE_LEAF,
WEBVTT_TIME_STAMP = 257 | WEBVTT_NODE_LEAF,
WEBVTT_NODE_LEAF_END = 257,
/* An empty initial state for a node */
WEBVTT_EMPTY_NODE = 258
} webvtt_node_kind;
/**
* Macros to assist in validating node kinds, so that C++ compilers don't
* complain (as long as they provide reinterpret_cast, which they should)
*/
#if defined(__cplusplus) || defined(__cplusplus_cli) || defined(__embedded_cplusplus) || defined(c_plusplus)
# define WEBVTT_CAST(Type,Val) (reinterpret_cast<Type>(Val))
#else
# define WEBVTT_CAST(Type,Val) ((Type)(Val))
#endif
#define WEBVTT_IS_LEAF(Kind) ( ((Kind) & WEBVTT_NODE_LEAF) != 0 )
#define WEBVTT_NODE_INDEX(Kind) ( (Kind) & ~WEBVTT_NODE_LEAF )
#define WEBVTT_IS_VALID_LEAF_NODE(Kind) ( WEBVTT_IS_LEAF(Kind) && (WEBVTT_NODE_INDEX(Kind) >= WEBVTT_NODE_LEAF_START && WEBVTT_NODE_INDEX(Kind) <= WEBVTT_NODE_LEAF_END ) )
#define WEBVTT_IS_VALID_INTERNAL_NODE(Kind) ( (!WEBVTT_IS_LEAF(Kind)) && (WEBVTT_NODE_INDEX(Kind) >= WEBVTT_NODE_INTERNAL_START && WEBVTT_NODE_INDEX(Kind) <= WEBVTT_NODE_INTERNAL_END) )
#define WEBVTT_IS_VALID_NODE_KIND(Kind) ( WEBVTT_IS_VALID_INTERNAL_NODE(Kind) || WEBVTT_IS_VALID_LEAF_NODE(Kind) )
/**
* Casting helpers
*/
#define WEBVTT_GET_INTERNAL_NODE(Node) ( WEBVTT_IS_VALID_INTERNAL_NODE(WEBVTT_CAST(webvtt_node,Node)->kind) ? WEBVTT_CAST(webvtt_internal_node,Node) : 0 )
#define WEBVTT_GET_LEAF_NODE(Node) ( WEBVTT_IS_VALID_LEAF_NODE((WEBVTT_CAST(webvtt_node,Node))->kind) ? WEBVTT_CAST(webvtt_leaf_node,Node) : 0 )
struct webvtt_internal_node_data_t;
typedef enum
webvtt_vertical_type_t {
WEBVTT_HORIZONTAL = 0,
@ -116,39 +55,6 @@ webvtt_align_type_t {
WEBVTT_ALIGN_RIGHT
} webvtt_align_type;
typedef struct
webvtt_node_t {
struct webvtt_refcount_t refs;
/**
* The specification asks for uni directional linked list, but we have added
* a parent node in order to facilitate an iterative cue text parsing
* solution.
*/
struct webvtt_node_t *parent;
webvtt_node_kind kind;
union {
webvtt_string text;
webvtt_timestamp timestamp;
struct webvtt_internal_node_data_t *internal_data;
} data;
} webvtt_node;
typedef struct
webvtt_internal_node_data_t {
webvtt_string annotation;
webvtt_stringlist *css_classes;
webvtt_uint alloc;
webvtt_uint length;
webvtt_node **children;
} webvtt_internal_node_data;
WEBVTT_EXPORT void webvtt_init_node( webvtt_node **node );
WEBVTT_EXPORT void webvtt_ref_node( webvtt_node *node );
WEBVTT_EXPORT void webvtt_release_node( webvtt_node **node );
typedef struct
webvtt_cue_settings_t {
webvtt_vertical_type vertical;

Просмотреть файл

@ -0,0 +1,119 @@
/**
* Copyright (c) 2013 Mozilla Foundation and Contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __WEBVTT_NODE_H__
# define __WEBVTT_NODE_H__
# include <webvtt/string.h>
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
typedef enum
webvtt_node_kind_t {
WEBVTT_NODE_LEAF = 0x80000000,
WEBVTT_NODE_INTERNAL = 0x00000000,
/**
* Internal Node objects
*/
WEBVTT_NODE_INTERNAL_START = 0,
WEBVTT_CLASS = 0 | WEBVTT_NODE_INTERNAL,
WEBVTT_ITALIC = 1 | WEBVTT_NODE_INTERNAL,
WEBVTT_BOLD = 2 | WEBVTT_NODE_INTERNAL,
WEBVTT_UNDERLINE = 3 | WEBVTT_NODE_INTERNAL,
WEBVTT_RUBY = 4 | WEBVTT_NODE_INTERNAL,
WEBVTT_RUBY_TEXT = 5 | WEBVTT_NODE_INTERNAL,
WEBVTT_VOICE = 6 | WEBVTT_NODE_INTERNAL,
/**
* This type of node has should not be rendered.
* It is the top of the node list and only contains a list of nodes.
*/
WEBVTT_HEAD_NODE = 7,
WEBVTT_NODE_INTERNAL_END = 7,
/**
* Leaf Node objects
*/
WEBVTT_NODE_LEAF_START = 256,
WEBVTT_TEXT = 256 | WEBVTT_NODE_LEAF,
WEBVTT_TIME_STAMP = 257 | WEBVTT_NODE_LEAF,
WEBVTT_NODE_LEAF_END = 257,
/* An empty initial state for a node */
WEBVTT_EMPTY_NODE = 258
} webvtt_node_kind;
#define WEBVTT_IS_LEAF(Kind) ( ((Kind) & WEBVTT_NODE_LEAF) != 0 )
#define WEBVTT_NODE_INDEX(Kind) ( (Kind) & ~WEBVTT_NODE_LEAF )
#define WEBVTT_IS_VALID_LEAF_NODE(Kind) ( WEBVTT_IS_LEAF(Kind) && (WEBVTT_NODE_INDEX(Kind) >= WEBVTT_NODE_LEAF_START && WEBVTT_NODE_INDEX(Kind) <= WEBVTT_NODE_LEAF_END ) )
#define WEBVTT_IS_VALID_INTERNAL_NODE(Kind) ( (!WEBVTT_IS_LEAF(Kind)) && (WEBVTT_NODE_INDEX(Kind) >= WEBVTT_NODE_INTERNAL_START && WEBVTT_NODE_INDEX(Kind) <= WEBVTT_NODE_INTERNAL_END) )
#define WEBVTT_IS_VALID_NODE_KIND(Kind) ( WEBVTT_IS_VALID_INTERNAL_NODE(Kind) || WEBVTT_IS_VALID_LEAF_NODE(Kind) )
struct webvtt_internal_node_data_t;
typedef struct
webvtt_node_t {
struct webvtt_refcount_t refs;
/**
* The specification asks for uni directional linked list, but we have added
* a parent node in order to facilitate an iterative cue text parsing
* solution.
*/
struct webvtt_node_t *parent;
webvtt_node_kind kind;
union {
webvtt_string text;
webvtt_timestamp timestamp;
struct webvtt_internal_node_data_t *internal_data;
} data;
} webvtt_node;
typedef struct
webvtt_internal_node_data_t {
webvtt_string annotation;
webvtt_stringlist *css_classes;
webvtt_uint alloc;
webvtt_uint length;
webvtt_node **children;
} webvtt_internal_node_data;
WEBVTT_EXPORT void webvtt_init_node( webvtt_node **node );
WEBVTT_EXPORT void webvtt_ref_node( webvtt_node *node );
WEBVTT_EXPORT void webvtt_release_node( webvtt_node **node );
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif

Просмотреть файл

@ -151,6 +151,15 @@ WEBVTT_EXPORT int webvtt_string_getline( webvtt_string *str, const webvtt_byte *
*/
WEBVTT_EXPORT webvtt_status webvtt_string_putc( webvtt_string *str, webvtt_byte to_append );
/**
* webvtt_string_is_equal
*
* compare a string's text to a byte array
*
*/
WEBVTT_EXPORT webvtt_bool webvtt_string_is_equal( webvtt_string *str, webvtt_byte *to_compare, webvtt_uint len );
/**
* webvtt_string_append
*

Просмотреть файл

@ -192,6 +192,17 @@ extern "C" {
* Parser should move to the next cuesetting.
*/
WEBVTT_NEXT_CUESETTING = -12,
/*
* Match is not found in a search query
*/
WEBVTT_NO_MATCH_FOUND = -13,
/**
* Thrown when assertions fail and FATAL_ASSERTION
* is not defined.
*/
WEBVTT_FAILED_ASSERTION = -14,
};
typedef enum webvtt_status_t webvtt_status;

218
media/webvtt/node.c Normal file
Просмотреть файл

@ -0,0 +1,218 @@
/**
* Copyright (c) 2013 Mozilla Foundation and Contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdlib.h>
#include "node_internal.h"
static webvtt_node empty_node = {
{ 1 }, /* init ref count */
0, /* parent */
WEBVTT_EMPTY_NODE /* node kind */
};
WEBVTT_EXPORT void
webvtt_ref_node( webvtt_node *node )
{
if( node ) {
webvtt_ref( &node->refs );
}
}
WEBVTT_EXPORT void
webvtt_init_node( webvtt_node **node )
{
if( *node != &empty_node ) {
if( node && *node ) {
webvtt_release_node( node );
}
*node = &empty_node;
webvtt_ref_node( *node );
}
}
WEBVTT_INTERN webvtt_status
webvtt_create_node( webvtt_node **node, webvtt_node_kind kind, webvtt_node *parent )
{
webvtt_node *temp_node;
if( !node ) {
return WEBVTT_INVALID_PARAM;
}
if( !( temp_node = (webvtt_node *)webvtt_alloc0(sizeof(*temp_node)) ) )
{
return WEBVTT_OUT_OF_MEMORY;
}
webvtt_ref_node( temp_node );
temp_node->kind = kind;
temp_node->parent = parent;
*node = temp_node;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_internal_node( webvtt_node **node, webvtt_node *parent, webvtt_node_kind kind,
webvtt_stringlist *css_classes, webvtt_string *annotation )
{
webvtt_status status;
webvtt_internal_node_data *node_data;
if( WEBVTT_FAILED( status = webvtt_create_node( node, kind, parent ) ) ) {
return status;
}
if ( !( node_data = (webvtt_internal_node_data *)webvtt_alloc0( sizeof(*node_data) ) ) )
{
return WEBVTT_OUT_OF_MEMORY;
}
webvtt_copy_stringlist( &node_data->css_classes, css_classes );
webvtt_copy_string( &node_data->annotation, annotation );
node_data->children = NULL;
node_data->length = 0;
node_data->alloc = 0;
(*node)->data.internal_data = node_data;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_head_node( webvtt_node **node )
{
webvtt_status status;
webvtt_string temp_annotation;
webvtt_init_string( &temp_annotation );
if( WEBVTT_FAILED( status = webvtt_create_internal_node( node, NULL, WEBVTT_HEAD_NODE, NULL, &temp_annotation ) ) ) {
return status;
}
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_timestamp_node( webvtt_node **node, webvtt_node *parent, webvtt_timestamp time_stamp )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_node( node, WEBVTT_TIME_STAMP, parent ) ) ) {
return status;
}
(*node)->data.timestamp = time_stamp;
return WEBVTT_SUCCESS;
}
WEBVTT_INTERN webvtt_status
webvtt_create_text_node( webvtt_node **node, webvtt_node *parent, webvtt_string *text )
{
webvtt_status status;
if( WEBVTT_FAILED( status = webvtt_create_node( node, WEBVTT_TEXT, parent ) ) ) {
return status;
}
webvtt_copy_string( &(*node)->data.text, text );
return WEBVTT_SUCCESS;
}
WEBVTT_EXPORT void
webvtt_release_node( webvtt_node **node )
{
webvtt_uint i;
webvtt_node *n;
if( !node || !*node ) {
return;
}
n = *node;
if( webvtt_deref( &n->refs ) == 0 ) {
if( n->kind == WEBVTT_TEXT ) {
webvtt_release_string( &n->data.text );
} else if( WEBVTT_IS_VALID_INTERNAL_NODE( n->kind ) && n->data.internal_data ) {
webvtt_release_stringlist( &n->data.internal_data->css_classes );
webvtt_release_string( &n->data.internal_data->annotation );
for( i = 0; i < n->data.internal_data->length; i++ ) {
webvtt_release_node( n->data.internal_data->children + i );
}
webvtt_free( n->data.internal_data->children );
webvtt_free( n->data.internal_data );
}
webvtt_free( n );
}
*node = 0;
}
WEBVTT_INTERN webvtt_status
webvtt_attach_node( webvtt_node *parent, webvtt_node *to_attach )
{
webvtt_node **next = 0;
webvtt_internal_node_data *nd = 0;
if( !parent || !to_attach || !parent->data.internal_data ) {
return WEBVTT_INVALID_PARAM;
}
nd = parent->data.internal_data;
if( nd->alloc == 0 ) {
next = (webvtt_node **)webvtt_alloc0( sizeof( webvtt_node * ) * 8 );
if( !next ) {
return WEBVTT_OUT_OF_MEMORY;
}
nd->children = next;
nd->alloc = 8;
}
if( nd->length + 1 >= ( nd->alloc / 3 ) * 2 ) {
next = (webvtt_node **)webvtt_alloc0( sizeof( *next ) * nd->alloc * 2 );
if( !next ) {
return WEBVTT_OUT_OF_MEMORY;
}
nd->alloc *= 2;
memcpy( next, nd->children, nd->length * sizeof( webvtt_node * ) );
webvtt_free( nd->children );
nd->children = next;
}
nd->children[ nd->length++ ] = to_attach;
webvtt_ref_node( to_attach );
return WEBVTT_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,50 @@
/**
* Copyright (c) 2013 Mozilla Foundation and Contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __WEBVTT_NODE_INTERNAL_H__
# define __WEBVTT_NODE_INTERNAL_H__
# include <webvtt/node.h>
/**
* Routines for creating nodes.
*/
WEBVTT_INTERN webvtt_status webvtt_create_node( webvtt_node **node, webvtt_node_kind kind, webvtt_node *parent );
WEBVTT_INTERN webvtt_status webvtt_create_internal_node( webvtt_node **node, webvtt_node *parent, webvtt_node_kind kind, webvtt_stringlist *css_classes, webvtt_string *annotation );
/**
* We probably shouldn't have a 'head node' type.
* We should just return a list of node trees...
*/
WEBVTT_INTERN webvtt_status webvtt_create_head_node( webvtt_node **node );
WEBVTT_INTERN webvtt_status webvtt_create_timestamp_node( webvtt_node **node, webvtt_node *parent, webvtt_timestamp time_stamp );
WEBVTT_INTERN webvtt_status webvtt_create_text_node( webvtt_node **node, webvtt_node *parent, webvtt_string *text );
/**
* Attaches a node to the internal node list of another node.
*/
WEBVTT_INTERN webvtt_status webvtt_attach_node( webvtt_node *parent, webvtt_node *to_attach );
#endif

Просмотреть файл

@ -42,9 +42,13 @@ static const webvtt_byte separator[] = {
#define BUFFER (self->buffer + self->position)
#define MALFORMED_TIME ((webvtt_timestamp_t)-1.0)
static int find_bytes( const webvtt_byte *buffer, webvtt_uint len, const webvtt_byte *sbytes, webvtt_uint slen );
static webvtt_status find_bytes( const webvtt_byte *buffer, webvtt_uint len, const webvtt_byte *sbytes, webvtt_uint slen );
static webvtt_status webvtt_skipwhite( const webvtt_byte *buffer, webvtt_uint *pos, webvtt_uint len );
static webvtt_int64 parse_int( const webvtt_byte **pb, int *pdigits );
static void skip_spacetab( const webvtt_byte *text, webvtt_uint *pos,
webvtt_uint len, webvtt_uint *column );
static void skip_until_white( const webvtt_byte *text, webvtt_uint *pos,
webvtt_uint len, webvtt_uint *column );
WEBVTT_EXPORT webvtt_status
webvtt_create_parser( webvtt_cue_fn on_read,
@ -229,6 +233,45 @@ find_newline( const webvtt_byte *buffer, webvtt_uint *pos, webvtt_uint len )
return -1;
}
static void
skip_spacetab( const webvtt_byte *text, webvtt_uint *pos, webvtt_uint len,
webvtt_uint *column )
{
webvtt_uint c = 0;
if( !column ) {
column = &c;
}
while( *pos < len ) {
webvtt_byte ch = text[ *pos ];
if( ch == 0x20 || ch == 0x09 ) {
++( *pos );
++( *column );
} else {
break;
}
}
}
static void
skip_until_white( const webvtt_byte *text, webvtt_uint *pos, webvtt_uint len,
webvtt_uint *column )
{
webvtt_uint c = 0;
if( !column ) {
column = &c;
}
while( *pos < len ) {
webvtt_byte ch = text[ *pos ];
if( ch == 0x20 || ch == 0x09 || ch == 0x0A || ch == 0x0D ) {
break;
} else {
int length = webvtt_utf8_length( text + *pos );
*pos += length;
++( *column );
}
}
}
static webvtt_status
webvtt_skipwhite( const webvtt_byte *buffer, webvtt_uint *pos, webvtt_uint len )
{
@ -259,25 +302,25 @@ find_next_whitespace( const webvtt_byte *buffer, webvtt_uint *ppos, webvtt_uint
/**
* basic strnstr-ish routine
*/
static int
static webvtt_status
find_bytes( const webvtt_byte *buffer, webvtt_uint len,
const webvtt_byte *sbytes, webvtt_uint slen )
{
webvtt_uint slen2;
// check params for integrity
if( !buffer || len < 1 || !sbytes || slen < 1 ) {
return 0;
return WEBVTT_INVALID_PARAM;
}
slen2 = slen - 1;
while( len-- >= slen && *buffer ){
if( *buffer == *sbytes && memcmp( buffer + 1, sbytes + 1, slen2 ) == 0 ) {
return 1;
return WEBVTT_SUCCESS;
}
buffer++;
}
return 0;
return WEBVTT_NO_MATCH_FOUND;
}
/**
@ -355,6 +398,243 @@ do \
} while(0)
#define POPBACK() do_pop(self)
static webvtt_status
webvtt_parse_cuesetting( webvtt_parser self, const webvtt_byte *text,
webvtt_uint *pos, webvtt_uint len, webvtt_error bv, webvtt_token
keyword, webvtt_token values[], webvtt_uint *value_column ) {
enum webvtt_param_mode
{
P_KEYWORD,
P_COLON,
P_VALUE
};
int i;
webvtt_bool precws = 0;
webvtt_bool prevws = 0;
static const webvtt_token value_tokens[] = {
INTEGER, RL, LR, START, MIDDLE, END, LEFT, RIGHT, PERCENTAGE, 0
};
static const webvtt_token keyword_tokens[] = {
ALIGN, SIZE, LINE, POSITION, VERTICAL, 0
};
enum webvtt_param_mode mode = P_KEYWORD;
webvtt_uint keyword_column = 0;
while( *pos < len ) {
webvtt_uint last_line = self->line;
webvtt_uint last_column = self->column;
webvtt_uint last_pos = *pos;
webvtt_token tk = webvtt_lex( self, text, pos, len, 1 );
webvtt_uint tp = self->token_pos;
self->token_pos = 0;
switch( mode ) {
case P_KEYWORD:
switch( tk ) {
case ALIGN:
case SIZE:
case POSITION:
case VERTICAL:
case LINE:
if( tk != keyword ) {
*pos -= tp;
self->column -= tp;
return WEBVTT_NEXT_CUESETTING;
}
if( *pos < len ) {
webvtt_uint column = last_column;
webvtt_byte ch = text[ *pos ];
if( ch != 0x3A ) {
webvtt_error e = WEBVTT_INVALID_CUESETTING;
if( ch == 0x20 || ch == 0x09 ) {
column = self->column;
e = WEBVTT_UNEXPECTED_WHITESPACE;
skip_spacetab( text, pos, len, &self->column );
if( text[ *pos ] == 0x3A ) {
skip_until_white( text, pos, len, &self->column );
}
} else {
skip_until_white( text, pos, len, &self->column );
}
ERROR_AT_COLUMN( e, column );
} else {
mode = P_COLON;
keyword_column = last_column;
}
} else {
ERROR_AT_COLUMN( WEBVTT_INVALID_CUESETTING, last_column );
}
break;
case WHITESPACE:
break;
case NEWLINE:
return WEBVTT_SUCCESS;
break;
default:
ERROR_AT( WEBVTT_INVALID_CUESETTING, last_line,
last_column );
*pos = *pos + tp + 1;
skip_param:
while( *pos < len && text[ *pos ] != 0x20
&& text[ *pos ] != 0x09 ) {
if( text[ *pos ] == 0x0A || text[ *pos ] == 0x0D ) {
return WEBVTT_SUCCESS;
}
++( *pos );
++self->column;
}
break;
}
break;
case P_COLON:
if( tk == WHITESPACE && !precws ) {
ERROR_AT( WEBVTT_UNEXPECTED_WHITESPACE, last_line,
last_column
);
precws = 1;
} else if( tk == COLON ) {
mode = P_VALUE;
} else if( token_in_list( tk, value_tokens ) ) {
ERROR_AT( WEBVTT_MISSING_CUESETTING_DELIMITER, last_line,
last_column );
mode = P_VALUE;
goto get_value;
} else if( token_in_list( tk, keyword_tokens ) ) {
ERROR_AT( WEBVTT_INVALID_CUESETTING, last_line,
keyword_column );
} else {
ERROR_AT( WEBVTT_INVALID_CUESETTING_DELIMITER, last_line,
last_column );
*pos = last_pos + tp + 1;
}
break;
case P_VALUE:
get_value:
if( tk == WHITESPACE && !prevws ) {
ERROR_AT( WEBVTT_UNEXPECTED_WHITESPACE, last_line,
last_column );
} else if( ( i = find_token( tk, values ) ) >= 0 ) {
webvtt_token t = values[ i ] & TF_TOKEN_MASK;
int flags = values[ i ] & TF_FLAGS_MASK;
*value_column = last_column;
if( *pos < len ) {
webvtt_byte ch = text[ *pos ];
if( ch != 0x20 && ch != 0x09
&& ch != 0x0D && ch != 0x0A ) {
goto bad_value;
}
}
switch( t ) {
case INTEGER:
case PERCENTAGE:
if( ( flags & TF_SIGN_MASK ) != TF_SIGN_MASK ) {
const webvtt_byte p = self->token[ 0 ];
if( ( ( flags & TF_NEGATIVE ) && p != UTF8_HYPHEN_MINUS )
|| ( ( flags & TF_POSITIVE ) && p == UTF8_HYPHEN_MINUS
) ) {
goto bad_value;
}
}
}
return i + 1;
} else {
bad_value:
ERROR_AT( bv, last_line, last_column );
bad_value_eol:
while( *pos < len && text[ *pos ] != 0x20
&& text[ *pos ] != 0x09 ) {
if( text[ *pos ] == 0x0A || text[ *pos ] == 0x0D ) {
return WEBVTT_SUCCESS;
}
++( *pos );
++self->column;
}
if( *pos >= len ) {
return WEBVTT_SUCCESS;
}
}
break;
}
}
if( mode == P_VALUE && *pos >= len ) {
ERROR( bv );
goto bad_value_eol;
}
return WEBVTT_NEXT_CUESETTING;
}
WEBVTT_INTERN webvtt_status
webvtt_parse_align( webvtt_parser self, webvtt_cue *cue, const
webvtt_byte *text,
webvtt_uint *pos, webvtt_uint len )
{
webvtt_uint last_line = self->line;
webvtt_uint last_column = self->column;
webvtt_status v;
webvtt_uint vc;
webvtt_token values[] = { START, MIDDLE, END, LEFT, RIGHT, 0 };
if( ( v = webvtt_parse_cuesetting( self, text, pos, len,
WEBVTT_ALIGN_BAD_VALUE, ALIGN, values, &vc ) ) > 0 ) {
if( cue->flags & CUE_HAVE_ALIGN ) {
ERROR_AT( WEBVTT_ALIGN_ALREADY_SET, last_line, last_column );
}
cue->flags |= CUE_HAVE_ALIGN;
switch( values[ v - 1 ] ) {
case START: cue->settings.align = WEBVTT_ALIGN_START; break;
case MIDDLE: cue->settings.align = WEBVTT_ALIGN_MIDDLE; break;
case END: cue->settings.align = WEBVTT_ALIGN_END; break;
case LEFT: cue->settings.align = WEBVTT_ALIGN_LEFT; break;
case RIGHT: cue->settings.align = WEBVTT_ALIGN_RIGHT; break;
}
}
return v >= 0 ? WEBVTT_SUCCESS : v;
}
WEBVTT_INTERN webvtt_status
webvtt_parse_line( webvtt_parser self, webvtt_cue *cue, const
webvtt_byte *text,
webvtt_uint *pos, webvtt_uint len )
{
webvtt_uint last_line = self->line;
webvtt_uint last_column = self->column;
webvtt_status v;
webvtt_uint vc;
webvtt_bool first_flag = 0;
webvtt_token values[] = { INTEGER, PERCENTAGE|TF_POSITIVE, 0 };
if( ( v = webvtt_parse_cuesetting( self, text, pos, len,
WEBVTT_LINE_BAD_VALUE, LINE, values, &vc ) ) > 0 ) {
webvtt_uint digits;
webvtt_int64 value;
const webvtt_byte *t = self->token;
if( cue->flags & CUE_HAVE_LINE ) {
ERROR_AT( WEBVTT_LINE_ALREADY_SET, last_line, last_column );
} else {
first_flag = 1;
}
cue->flags |= CUE_HAVE_LINE;
value = parse_int( &t, &digits );
switch( values[ v - 1 ] & TF_TOKEN_MASK ) {
case INTEGER: {
cue->snap_to_lines = 1;
cue->settings.line = ( int )value;
}
break;
case PERCENTAGE: {
if( value < 0 || value > 100 ) {
if( first_flag ) {
cue->flags &= ~CUE_HAVE_LINE;
}
ERROR_AT_COLUMN( WEBVTT_LINE_BAD_VALUE, vc );
return WEBVTT_SUCCESS;
}
cue->snap_to_lines = 0;
cue->settings.line = ( int )value;
} break;
}
}
return v >= 0 ? WEBVTT_SUCCESS : v;
}
WEBVTT_INTERN int
parse_cueparams( webvtt_parser self, const webvtt_byte *buffer,
webvtt_uint len, webvtt_cue *cue )
@ -365,6 +645,8 @@ parse_cueparams( webvtt_parser self, const webvtt_byte *buffer,
webvtt_uint baddelim = 0;
webvtt_uint pos = 0;
webvtt_token last_token = 0;
webvtt_uint last_line = self->line;
enum cp_state {
CP_T1, CP_T2, CP_T3, CP_T4, CP_T5, /* 'start' cuetime, whitespace1,
'separator', whitespace2, 'end' cuetime */
@ -396,6 +678,8 @@ parse_cueparams( webvtt_parser self, const webvtt_byte *buffer,
while( pos < len ) {
webvtt_uint last_column = self->column;
webvtt_token token = webvtt_lex( self, buffer, &pos, len, 1 );
webvtt_uint tlen = self->token_pos;
self->token_pos = 0;
_recheck:
switch( state ) {
/* start timestamp */
@ -409,7 +693,7 @@ _recheck:
( BAD_TIMESTAMP( cue->from )
? WEBVTT_EXPECTED_TIMESTAMP
: WEBVTT_MALFORMED_TIMESTAMP ), last_column );
if( !webvtt_isdigit( self->token[self->token_pos - 1] ) ) {
if( self->token_pos && !webvtt_isdigit( self->token[self->token_pos - 1] ) ) {
while( pos < len && buffer[pos] != 0x09 && buffer[pos] != 0x20 ) { ++pos; }
}
if( BAD_TIMESTAMP( cue->from ) )
@ -513,9 +797,6 @@ else if( !have_ws ) \
case WHITESPACE:
have_ws = last_column;
break;
case COLON:
ERROR_AT_COLUMN( WEBVTT_MISSING_CUESETTING_KEYWORD, last_column );
break;
case VERTICAL:
CHKDELIM have_ws = 0;
SETST( CP_V1 );
@ -525,21 +806,35 @@ else if( !have_ws ) \
SETST( CP_P1 );
break;
case ALIGN:
CHKDELIM have_ws = 0;
SETST( CP_A1 );
{
webvtt_status status;
pos -= tlen; /* Required for parse_align() */
self->column = last_column; /* Reset for parse_align() */
status = webvtt_parse_align( self, cue, buffer, &pos, len );
if( status == WEBVTT_PARSE_ERROR ) {
return WEBVTT_PARSE_ERROR;
}
}
break;
case SIZE:
CHKDELIM have_ws = 0;
SETST( CP_S1 );
break;
case LINE:
CHKDELIM have_ws = 0;
SETST( CP_L1 );
{
webvtt_status status;
pos -= tlen; /* Required for parse_align() */
self->column = last_column; /* Reset for parse_align() */
status = webvtt_parse_line( self, cue, buffer, &pos, len );
if( status == WEBVTT_PARSE_ERROR ) {
return WEBVTT_PARSE_ERROR;
}
}
break;
default:
if( have_ws ) {
ERROR_AT_COLUMN( WEBVTT_INVALID_CUESETTING, last_column );
while( pos < len && buffer[pos] != 0x09 && buffer[pos] != 0x20 ) { ++pos; }
} else if( token == BADTOKEN ) {
/* it was a bad delimiter... */
if( !baddelim ) {
@ -547,6 +842,9 @@ else if( !have_ws ) \
}
++pos;
}
while( pos < len && buffer[pos] != 0x09 && buffer[pos] != 0x20 ) {
++pos;
}
}
break;
#define CS1(S) \
@ -1018,6 +1316,13 @@ _recheck:
webvtt_state *st = FRAMEUP( 1 );
webvtt_string text = st->v.text;
/* FIXME: guard inconsistent state */
if (!cue) {
ERROR( WEBVTT_PARSE_ERROR );
status = WEBVTT_PARSE_ERROR;
goto _finish;
}
st->type = V_NONE;
st->v.cue = NULL;
@ -1027,7 +1332,7 @@ _recheck:
* TODO: Add debug assertion
*/
if( find_bytes( webvtt_string_text( &text ), webvtt_string_length( &text ), separator,
sizeof( separator ) ) ) {
sizeof( separator ) ) == WEBVTT_SUCCESS) {
/* It's not a cue id, we found '-->'. It can't be a second
cueparams line, because if we had it, we would be in
a different state. */
@ -1051,7 +1356,7 @@ _recheck:
}
} else {
/* It is a cue-id */
if( cue->flags & CUE_HAVE_ID ) {
if( cue && cue->flags & CUE_HAVE_ID ) {
/**
* This isn't actually a cue-id, because we already
* have one. It seems to be cuetext, which is occurring
@ -1122,24 +1427,17 @@ read_cuetext( webvtt_parser self, const webvtt_byte *b, webvtt_uint
goto _finish;
}
if( self->line_buffer.d->length > 1 && self->line_buffer.d->text[ self->line_buffer.d->length - 1 ] == UTF8_LINE_FEED ) {
/**
* We've encountered a line without any cuetext on it, i.e. there is no
* newline character and len is 0 or there is and len is 1, therefore,
* the cue text is finished.
*/
if( self->line_buffer.d->length <= 1 ) {
/**
* finished
*/
finished = 1;
}
webvtt_string_putc( &self->line_buffer, UTF8_LINE_FEED );
if( pos < len ) {
if( b[pos] == UTF8_CARRIAGE_RETURN ) {
if( len - pos >= 2 && b[pos + 1] == UTF8_LINE_FEED ) {
++pos;
}
++pos;
} else {
++pos;
}
}
}
} while( pos < len && !finished );
_finish:
@ -1385,3 +1683,31 @@ _malformed:
*result = 0xFFFFFFFFFFFFFFFF;
return 0;
}
WEBVTT_INTERN webvtt_bool
token_in_list( webvtt_token token, const webvtt_token list[] )
{
int i = 0;
webvtt_token t;
while( ( t = list[ i++ ] ) != 0 ) {
if( token == t ) {
return 1;
}
}
return 0;
}
WEBVTT_INTERN int
find_token( webvtt_token token, const webvtt_token list[] )
{
int i = 0;
webvtt_token t;
while( ( t = list[ i ] ) != 0 ) {
webvtt_token masked = t & TF_TOKEN_MASK;
if( token == masked ) {
return i;
}
++i;
}
return -1;
}

Просмотреть файл

@ -29,6 +29,18 @@
# define __INTERN_PARSER_H__
# include <webvtt/parser.h>
# include "string_internal.h"
# ifndef NDEBUG
# define NDEBUG
# endif
# if defined(FATAL_ASSERTION)
# undef NDEBUG
# include <assert.h>
# else
# if defined(BREAK_ON_ASSERTION) && !WEBVTT_OS_WIN32
static void break_on_assert();
# endif
# endif
typedef enum
webvtt_token_t {
@ -217,20 +229,102 @@ WEBVTT_INTERN webvtt_token webvtt_lex( webvtt_parser self, const webvtt_byte *bu
WEBVTT_INTERN webvtt_status webvtt_lex_word( webvtt_parser self, webvtt_string *pba, const webvtt_byte *buffer, webvtt_uint *pos, webvtt_uint length, webvtt_bool finish );
WEBVTT_INTERN int parse_timestamp( const webvtt_byte *b, webvtt_timestamp *result );
/**
* Flags which can apply additional meaning to a token. find_token() will
* test for only the actual token and ignore the additional flags.
*/
typedef
enum webvtt_token_flags_t
{
/* Number can be positive */
TF_POSITIVE = 0x80000000,
/* Number can be negative */
TF_NEGATIVE = 0x40000000,
/* (token & TF_SIGN_MASK) == combination of TF_POSITIVE and
TF_NEGATIVE, which indicate what values a number token is allowed
to be */
TF_SIGN_MASK = ( TF_POSITIVE | TF_NEGATIVE ),
/* (token & TF_FLAGS_MASK) == webvtt_token_flags value
that is being asked for */
TF_FLAGS_MASK = TF_SIGN_MASK,
/* (token & TF_TOKEN_MASK) == webvtt_token value */
TF_TOKEN_MASK = ( 0xFFFFFFFF & ~TF_FLAGS_MASK ),
} webvtt_token_flags;
/**
* Return non-zero if a token is found in a NULL-terminated array of tokens, or
* zero if not.
*
* Unlike find_token(), token_in_list() does not make use of
* webvtt_token_flags and thus requiers an exact match.
*/
WEBVTT_INTERN webvtt_bool token_in_list( webvtt_token search_for,
const webvtt_token token_list[] );
/**
* Return the index of a token in a NULL-terminated array of tokens,
* or -1 if the token is not found.
*
* find_token() will search for an occurrence of `token' in a list
* where webvtt_token_flags are used. For instance, if the list of
* tokens contains { TF_POSITIVE | INTEGER, TF_POSITIVE | PERCENTAGE,
* 0 }, find_token() will return a match for INTEGER or PERCENTAGE if
* either is searched for.
*/
WEBVTT_INTERN int find_token( webvtt_token search_for,
const webvtt_token token_list[] );
#define BAD_TIMESTAMP(ts) ( ( ts ) == 0xFFFFFFFFFFFFFFFF )
#define ERROR(Code) \
do \
{ \
if( !self->error || self->error(self->userdata,self->line,self->column,Code) < 0 ) \
return WEBVTT_PARSE_ERROR; \
} while(0)
#define ERROR_AT_COLUMN(Code,Column) \
do \
{ \
if( !self->error || self->error(self->userdata,self->line,(Column),Code) < 0 ) \
return WEBVTT_PARSE_ERROR; \
} while(0)
#ifdef FATAL_ASSERTION
# define SAFE_ASSERT(condition) assert(condition)
# define DIE_IF(condition) assert( !(condition) )
#else
# ifdef BREAK_ON_ASSERTION
static void
break_on_assert(void) {
#if WEBVTT_OS_WIN32
/* __declspec(dllimport) should work for cross compiling gcc as well */
__declspec(dllimport) void __stdcall DebugBreak( void );
DebugBreak();
#else
volatile int *ptr = (volatile int *)0;
*ptr = 1;
#endif
}
# define SAFE_ASSERT(condition) \
if( !(condition) ) { \
break_on_assert(); \
return WEBVTT_FAILED_ASSERTION; \
}
# define DIE_IF(condition) \
if( (condition) ) { \
break_on_assert(); \
}
# else
# define SAFE_ASSERT(condition) \
if( !(condition) ) { \
return WEBVTT_FAILED_ASSERTION; \
}
# define DIE_IF(condition)
# endif
#endif
#define ERROR_AT(errno, line, column) \
do \
{ \
if( !self->error \
|| self->error( (self->userdata), (line), (column), (errno) ) < 0 ) { \
return WEBVTT_PARSE_ERROR; \
} \
} while(0)
#define ERROR(error) \
ERROR_AT( (error), (self->line), (self->column) )
#define ERROR_AT_COLUMN(error, column) \
ERROR_AT( (error), (self->line), (column) )
#endif

Просмотреть файл

@ -180,7 +180,6 @@ WEBVTT_EXPORT void
webvtt_copy_string( webvtt_string *left, const webvtt_string *right )
{
if( left ) {
webvtt_string_data *d = left->d;
if( right && right->d ) {
left->d = right->d;
} else {
@ -332,7 +331,7 @@ webvtt_string_getline( webvtt_string *src, const webvtt_byte *buffer,
/* truncate. */
(*truncate)++;
} else {
if( grow( str, len ) == WEBVTT_OUT_OF_MEMORY ) {
if( grow( str, len + 1 ) == WEBVTT_OUT_OF_MEMORY ) {
ret = -1;
}
d = str->d;
@ -371,6 +370,15 @@ webvtt_string_putc( webvtt_string *str, webvtt_byte to_append )
return result;
}
WEBVTT_EXPORT webvtt_bool
webvtt_string_is_equal( webvtt_string *str, webvtt_byte *to_compare, webvtt_uint len )
{
if( !str || !to_compare || webvtt_string_length( str ) != len ) {
return 0;
}
return memcmp( webvtt_string_text( str ), to_compare, len ) == 0;
}
WEBVTT_EXPORT webvtt_status
webvtt_string_append( webvtt_string *str, const webvtt_byte *buffer, int len )
{