src/tokeniser/tokeniser.c
hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
{
	hubbub_tag *ctag = &tokeniser->context.current_tag;

	size_t len;
	const uint8_t *cptr;
	parserutils_error error;
	uint8_t c;

	assert(tokeniser->context.pending == 1);
/*	assert(tokeniser->context.chars.ptr[0] == '<'); */

	error = parserutils_inputstream_peek(tokeniser->input, 
			tokeniser->context.pending, &cptr, &len);

	if (error != PARSERUTILS_OK) {
		if (error == PARSERUTILS_EOF) {
			/* Return to data state with '<' still in "chars" */
			tokeniser->state = STATE_DATA;
			return HUBBUB_OK;
		} else {
			return hubbub_error_from_parserutils_error(error);
		}
	}

	c = *cptr;

	if (c == '/') {
		tokeniser->context.pending += len;

		tokeniser->context.close_tag_match.match = false;
		tokeniser->context.close_tag_match.count = 0;

		tokeniser->state = STATE_CLOSE_TAG_OPEN;
	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA ||
			tokeniser->content_model ==
					HUBBUB_CONTENT_MODEL_CDATA) {
		/* Return to data state with '<' still in "chars" */
		tokeniser->state = STATE_DATA;
	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA) {
		if (c == '!') {
			parserutils_inputstream_advance(tokeniser->input,
					SLEN("<!"));

			tokeniser->context.pending = 0;
			tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
		} else if ('A' <= c && c <= 'Z') {
			uint8_t lc = (c + 0x20);

			START_BUF(ctag->name, &lc, len);
			ctag->n_attributes = 0;
			tokeniser->context.current_tag_type =
					HUBBUB_TOKEN_START_TAG;

			tokeniser->context.pending += len;

			tokeniser->state = STATE_TAG_NAME;
		} else if ('a' <= c && c <= 'z') {
			START_BUF(ctag->name, cptr, len);
			ctag->n_attributes = 0;
			tokeniser->context.current_tag_type =
					HUBBUB_TOKEN_START_TAG;

			tokeniser->context.pending += len;

			tokeniser->state = STATE_TAG_NAME;
		} else if (c == '>') {
			/** \todo parse error */

			tokeniser->context.pending += len;
			tokeniser->state = STATE_DATA;
		} else if (c == '?') {
			/** \todo parse error */

			/* Cursor still at "<", need to advance past it */
			parserutils_inputstream_advance(
					tokeniser->input, SLEN("<"));
			tokeniser->context.pending = 0;

			tokeniser->state = STATE_BOGUS_COMMENT;
		} else {
			/* Return to data state with '<' still in "chars" */
			tokeniser->state = STATE_DATA;
		}
	}

	return HUBBUB_OK;
}
/* this state always switches to another state straight away */
/* this state expects the current character to be '<' */
this state always switches to another state straight away
this state expects the current character to be '<'
this state always switches to another state straight away this state expects the current character to be ' < '
hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
{
	hubbub_tag *ctag = &tokeniser->context.current_tag;
	size_t len;
	const uint8_t *cptr;
	parserutils_error error;
	uint8_t c;
	assert(tokeniser->context.pending == 1);
	error = parserutils_inputstream_peek(tokeniser->input, 
			tokeniser->context.pending, &cptr, &len);
	if (error != PARSERUTILS_OK) {
		if (error == PARSERUTILS_EOF) {
			tokeniser->state = STATE_DATA;
			return HUBBUB_OK;
		} else {
			return hubbub_error_from_parserutils_error(error);
		}
	}
	c = *cptr;
	if (c == '/') {
		tokeniser->context.pending += len;
		tokeniser->context.close_tag_match.match = false;
		tokeniser->context.close_tag_match.count = 0;
		tokeniser->state = STATE_CLOSE_TAG_OPEN;
	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA ||
			tokeniser->content_model ==
					HUBBUB_CONTENT_MODEL_CDATA) {
		tokeniser->state = STATE_DATA;
	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA) {
		if (c == '!') {
			parserutils_inputstream_advance(tokeniser->input,
					SLEN("<!"));
			tokeniser->context.pending = 0;
			tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
		} else if ('A' <= c && c <= 'Z') {
			uint8_t lc = (c + 0x20);
			START_BUF(ctag->name, &lc, len);
			ctag->n_attributes = 0;
			tokeniser->context.current_tag_type =
					HUBBUB_TOKEN_START_TAG;
			tokeniser->context.pending += len;
			tokeniser->state = STATE_TAG_NAME;
		} else if ('a' <= c && c <= 'z') {
			START_BUF(ctag->name, cptr, len);
			ctag->n_attributes = 0;
			tokeniser->context.current_tag_type =
					HUBBUB_TOKEN_START_TAG;
			tokeniser->context.pending += len;
			tokeniser->state = STATE_TAG_NAME;
		} else if (c == '>') {
			tokeniser->context.pending += len;
			tokeniser->state = STATE_DATA;
		} else if (c == '?') {
			parserutils_inputstream_advance(
					tokeniser->input, SLEN("<"));
			tokeniser->context.pending = 0;
			tokeniser->state = STATE_BOGUS_COMMENT;
		} else {
			tokeniser->state = STATE_DATA;
		}
	}
	return HUBBUB_OK;
}
hubbub_error hubbub_tokeniser_handle_tag_open ( hubbub_tokeniser * tokeniser ) { hubbub_tag * ctag = & tokeniser -> context . current_tag ; size_t len ; const uint8_t * cptr ; parserutils_error error ; uint8_t c ; assert ( tokeniser -> context . pending == 1 ) ; error = parserutils_inputstream_peek ( tokeniser -> input , tokeniser -> context . pending , & cptr , & len ) ; if ( error != PARSERUTILS_OK ) { if ( error == PARSERUTILS_EOF ) { tokeniser -> state = STATE_DATA ; return HUBBUB_OK ; } else { return hubbub_error_from_parserutils_error ( error ) ; } } c = * cptr ; if ( c == ' ' ) { tokeniser -> context . pending += len ; tokeniser -> context . close_tag_match . match = false ; tokeniser -> context . close_tag_match . count = 0 ; tokeniser -> state = STATE_CLOSE_TAG_OPEN ; } else if ( tokeniser -> content_model == HUBBUB_CONTENT_MODEL_RCDATA || tokeniser -> content_model == HUBBUB_CONTENT_MODEL_CDATA ) { tokeniser -> state = STATE_DATA ; } else if ( tokeniser -> content_model == HUBBUB_CONTENT_MODEL_PCDATA ) { if ( c == ' ' ) { parserutils_inputstream_advance ( tokeniser -> input , SLEN ( " " ) ) ; tokeniser -> context . pending = 0 ; tokeniser -> state = STATE_MARKUP_DECLARATION_OPEN ; } else if ( ' ' <= c && c <= ' ' ) { uint8_t lc = ( c + 0x20 ) ; START_BUF ( ctag -> name , & lc , len ) ; ctag -> n_attributes = 0 ; tokeniser -> context . current_tag_type = HUBBUB_TOKEN_START_TAG ; tokeniser -> context . pending += len ; tokeniser -> state = STATE_TAG_NAME ; } else if ( ' ' <= c && c <= ' ' ) { START_BUF ( ctag -> name , cptr , len ) ; ctag -> n_attributes = 0 ; tokeniser -> context . current_tag_type = HUBBUB_TOKEN_START_TAG ; tokeniser -> context . pending += len ; tokeniser -> state = STATE_TAG_NAME ; } else if ( c == ' ' ) { tokeniser -> context . pending += len ; tokeniser -> state = STATE_DATA ; } else if ( c == ' ' ) { parserutils_inputstream_advance ( tokeniser -> input , SLEN ( " " ) ) ; tokeniser -> context . pending = 0 ; tokeniser -> state = STATE_BOGUS_COMMENT ; } else { tokeniser -> state = STATE_DATA ; } } return HUBBUB_OK ; }
this state always switches to another state straight away
this state expects the current character to be '<'
this state always switches to another state straight away this state expects the current character to be ' < '
/*	assert(tokeniser->context.chars.ptr[0] == '<'); */ /* Return to data state with '<' still in "chars" */ /* Return to data state with '<' still in "chars" */ /** \todo parse error */ /** \todo parse error */ /* Cursor still at "<", need to advance past it */ /* Return to data state with '<' still in "chars" */