src/tokeniser/tokeniser.c
hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser)
{
	hubbub_error err;
	hubbub_token token;
	uint32_t n_attributes;
	hubbub_attribute *attrs;
	uint8_t *ptr;
	uint32_t i, j;

	/* Emit current tag */
	token.type = tokeniser->context.current_tag_type;
	token.data.tag = tokeniser->context.current_tag;
 	token.data.tag.ns = HUBBUB_NS_HTML;


	n_attributes = token.data.tag.n_attributes;
	attrs = token.data.tag.attributes;

	/* Set pointers correctly... */
	ptr = tokeniser->buffer->data;
	token.data.tag.name.ptr = tokeniser->buffer->data;
	ptr += token.data.tag.name.len;

	for (i = 0; i < n_attributes; i++) {
		attrs[i].name.ptr = ptr;
		ptr += attrs[i].name.len;
		attrs[i].value.ptr = ptr;
		ptr += attrs[i].value.len;
	}


	/* Discard duplicate attributes */
	for (i = 0; i < n_attributes; i++) {
		for (j = 0; j < n_attributes; j++) {
			uint32_t move;

			if (j == i ||
				attrs[i].name.len !=
						attrs[j].name.len ||
				strncmp((char *) attrs[i].name.ptr,
					(char *) attrs[j].name.ptr,
					attrs[i].name.len) != 0) {
				/* Attributes don't match */
				continue;
			}

			assert(i < j);

			/* Calculate amount to move */
			move = (n_attributes - 1 - j) *
					sizeof(hubbub_attribute);

			if (move > 0) {
				memmove(&attrs[j],&attrs[j+1], move);
			}

			/* We've deleted an item, so we need to 
			 * reprocess this index */
			j--;

			/* And reduce the number of attributes */
			n_attributes--;
		}
	}

	token.data.tag.n_attributes = n_attributes;

	err = hubbub_tokeniser_emit_token(tokeniser, &token);

	if (token.type == HUBBUB_TOKEN_START_TAG) {
		/* Save start tag name for R?CDATA */
		if (token.data.tag.name.len <
			sizeof(tokeniser->context.last_start_tag_name)) {
			strncpy((char *) tokeniser->context.last_start_tag_name,
				(const char *) token.data.tag.name.ptr,
				token.data.tag.name.len);
			tokeniser->context.last_start_tag_len =
					token.data.tag.name.len;
		} else {
			tokeniser->context.last_start_tag_name[0] = '\0';
			tokeniser->context.last_start_tag_len = 0;
		}
	} else /* if (token->type == HUBBUB_TOKEN_END_TAG) */ {
		/* Reset content model after R?CDATA elements */
		tokeniser->content_model = HUBBUB_CONTENT_MODEL_PCDATA;
	}

	/* Reset the self-closing flag */
	tokeniser->context.current_tag.self_closing = false;

	return err;
}
/**
 * Emit the current tag token being stored in the tokeniser context.
 *
 * \param tokeniser	Tokeniser instance
 * \return	true
 */
Emit the current tag token being stored in the tokeniser context.
\param tokeniser     Tokeniser instance
\return      true
Emit the current tag token being stored in the tokeniser context . \ param tokeniser Tokeniser instance \ return true
hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser)
{
	hubbub_error err;
	hubbub_token token;
	uint32_t n_attributes;
	hubbub_attribute *attrs;
	uint8_t *ptr;
	uint32_t i, j;
	token.type = tokeniser->context.current_tag_type;
	token.data.tag = tokeniser->context.current_tag;
 	token.data.tag.ns = HUBBUB_NS_HTML;
	n_attributes = token.data.tag.n_attributes;
	attrs = token.data.tag.attributes;
	ptr = tokeniser->buffer->data;
	token.data.tag.name.ptr = tokeniser->buffer->data;
	ptr += token.data.tag.name.len;
	for (i = 0; i < n_attributes; i++) {
		attrs[i].name.ptr = ptr;
		ptr += attrs[i].name.len;
		attrs[i].value.ptr = ptr;
		ptr += attrs[i].value.len;
	}
	for (i = 0; i < n_attributes; i++) {
		for (j = 0; j < n_attributes; j++) {
			uint32_t move;
			if (j == i ||
				attrs[i].name.len !=
						attrs[j].name.len ||
				strncmp((char *) attrs[i].name.ptr,
					(char *) attrs[j].name.ptr,
					attrs[i].name.len) != 0) {
				continue;
			}
			assert(i < j);
			move = (n_attributes - 1 - j) *
					sizeof(hubbub_attribute);
			if (move > 0) {
				memmove(&attrs[j],&attrs[j+1], move);
			}
			j--;
			n_attributes--;
		}
	}
	token.data.tag.n_attributes = n_attributes;
	err = hubbub_tokeniser_emit_token(tokeniser, &token);
	if (token.type == HUBBUB_TOKEN_START_TAG) {
		if (token.data.tag.name.len <
			sizeof(tokeniser->context.last_start_tag_name)) {
			strncpy((char *) tokeniser->context.last_start_tag_name,
				(const char *) token.data.tag.name.ptr,
				token.data.tag.name.len);
			tokeniser->context.last_start_tag_len =
					token.data.tag.name.len;
		} else {
			tokeniser->context.last_start_tag_name[0] = '\0';
			tokeniser->context.last_start_tag_len = 0;
		}
	} else  {
		tokeniser->content_model = HUBBUB_CONTENT_MODEL_PCDATA;
	}
	tokeniser->context.current_tag.self_closing = false;
	return err;
}
hubbub_error emit_current_tag ( hubbub_tokeniser * tokeniser ) { hubbub_error err ; hubbub_token token ; uint32_t n_attributes ; hubbub_attribute * attrs ; uint8_t * ptr ; uint32_t i , j ; token . type = tokeniser -> context . current_tag_type ; token . data . tag = tokeniser -> context . current_tag ; token . data . tag . ns = HUBBUB_NS_HTML ; n_attributes = token . data . tag . n_attributes ; attrs = token . data . tag . attributes ; ptr = tokeniser -> buffer -> data ; token . data . tag . name . ptr = tokeniser -> buffer -> data ; ptr += token . data . tag . name . len ; for ( i = 0 ; i < n_attributes ; i ++ ) { attrs [ i ] . name . ptr = ptr ; ptr += attrs [ i ] . name . len ; attrs [ i ] . value . ptr = ptr ; ptr += attrs [ i ] . value . len ; } for ( i = 0 ; i < n_attributes ; i ++ ) { for ( j = 0 ; j < n_attributes ; j ++ ) { uint32_t move ; if ( j == i || attrs [ i ] . name . len != attrs [ j ] . name . len || strncmp ( ( char * ) attrs [ i ] . name . ptr , ( char * ) attrs [ j ] . name . ptr , attrs [ i ] . name . len ) != 0 ) { continue ; } assert ( i < j ) ; move = ( n_attributes - 1 - j ) * sizeof ( hubbub_attribute ) ; if ( move > 0 ) { memmove ( & attrs [ j ] , & attrs [ j + 1 ] , move ) ; } j -- ; n_attributes -- ; } } token . data . tag . n_attributes = n_attributes ; err = hubbub_tokeniser_emit_token ( tokeniser , & token ) ; if ( token . type == HUBBUB_TOKEN_START_TAG ) { if ( token . data . tag . name . len < sizeof ( tokeniser -> context . last_start_tag_name ) ) { strncpy ( ( char * ) tokeniser -> context . last_start_tag_name , ( const char * ) token . data . tag . name . ptr , token . data . tag . name . len ) ; tokeniser -> context . last_start_tag_len = token . data . tag . name . len ; } else { tokeniser -> context . last_start_tag_name [ 0 ] = ' \0 ' ; tokeniser -> context . last_start_tag_len = 0 ; } } else { tokeniser -> content_model = HUBBUB_CONTENT_MODEL_PCDATA ; } tokeniser -> context . current_tag . self_closing = false ; return err ; }
Emit the current tag token being stored in the tokeniser context.
Emit the current tag token being stored in the tokeniser context .
/* Emit current tag */ /* Set pointers correctly... */ /* Discard duplicate attributes */ /* Attributes don't match */ /* Calculate amount to move */ /* We've deleted an item, so we need to 
			 * reprocess this index */ /* And reduce the number of attributes */ /* Save start tag name for R?CDATA */ /* if (token->type == HUBBUB_TOKEN_END_TAG) */ /* Reset content model after R?CDATA elements */ /* Reset the self-closing flag */