doubango/tinySDP/ragel/tsdp_parser_message.rl
c732d49e
 /*
 * Copyright (C) 2010-2015 Mamadou Diop.
 *	
 * This file is part of Open Source Doubango Framework.
 *
 * DOUBANGO is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *	
 * DOUBANGO is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *	
 * You should have received a copy of the GNU General Public License
 * along with DOUBANGO.
 *
 */
 /**@file tsdp_machine_message.rl
  * @brief Ragel file.
  */
 #include "tinysdp/parsers/tsdp_parser_message.h"
 
 #include "tinysdp/headers/tsdp_header_A.h"
 #include "tinysdp/headers/tsdp_header_B.h"
 #include "tinysdp/headers/tsdp_header_C.h"
 #include "tinysdp/headers/tsdp_header_Dummy.h"
 #include "tinysdp/headers/tsdp_header_E.h"
 #include "tinysdp/headers/tsdp_header_I.h"
 #include "tinysdp/headers/tsdp_header_K.h"
 #include "tinysdp/headers/tsdp_header_M.h"
 #include "tinysdp/headers/tsdp_header_O.h"
 #include "tinysdp/headers/tsdp_header_P.h"
 #include "tinysdp/headers/tsdp_header_R.h"
 #include "tinysdp/headers/tsdp_header_S.h"
 #include "tinysdp/headers/tsdp_header_T.h"
 #include "tinysdp/headers/tsdp_header_U.h"
 #include "tinysdp/headers/tsdp_header_V.h"
 #include "tinysdp/headers/tsdp_header_Z.h"
 
 #include "tsk_debug.h"
 
 %%{
 	machine tsdp_machine_message;
 	
 	###########################################
 	#	Includes
 	###########################################
 	include tsdp_machine_utils "./ragel/tsdp_machine_utils.rl";
 	
 	action tag{
 		tag_start = p;
 	}
 
 	###########################################
 	#	Actions
 	###########################################
 	action parse_header_A{
 		if(hdr_M){
 			if(!hdr_M->Attributes){
 				hdr_M->Attributes = tsk_list_create();
 			}
 			if((header = (tsdp_header_t*)tsdp_header_A_parse(tag_start, (p - tag_start)))){
 				tsk_list_push_back_data(hdr_M->Attributes, (void**)&header);
 			}
 		}
 		else if((header = (tsdp_header_t*)tsdp_header_A_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 
 	action parse_header_B{
 		if(hdr_M){
 			if(!hdr_M->Bandwidths){
 				hdr_M->Bandwidths = tsk_list_create();
 			}
 			if((header = (tsdp_header_t*)tsdp_header_B_parse(tag_start, (p - tag_start)))){
 				tsk_list_push_back_data(hdr_M->Bandwidths, (void**)&header);
 			}
 		}
 		else if((header = (tsdp_header_t*)tsdp_header_B_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_C{
 		if(hdr_M && !hdr_M->C){
 			hdr_M->C = tsdp_header_C_parse(tag_start, (p - tag_start));
 		}
 		else if((header = (tsdp_header_t*)tsdp_header_C_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_Dummy{
 		if((header = (tsdp_header_t*)tsdp_header_Dummy_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_E{
 		if((header = (tsdp_header_t*)tsdp_header_E_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_I{
 		if(hdr_M && !hdr_M->I){
 			hdr_M->I = tsdp_header_I_parse(tag_start, (p - tag_start));
 		}
 		else if((header = (tsdp_header_t*)tsdp_header_I_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_K{
 		if(hdr_M && !hdr_M->K){
 			hdr_M->K = tsdp_header_K_parse(tag_start, (p - tag_start));
 		}
 		else if((header = (tsdp_header_t*)tsdp_header_K_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_M{
 		if((hdr_M = tsdp_header_M_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, TSDP_HEADER(hdr_M));
 			hdr_M = tsk_object_unref(hdr_M);
 		}
 	}
 	
 	action parse_header_O{
 		if((header = (tsdp_header_t*)tsdp_header_O_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_P{
 		if((header = (tsdp_header_t*)tsdp_header_P_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 
 	action parse_header_R{
 		if((header = (tsdp_header_t*)tsdp_header_R_parse(tag_start, (p - tag_start)))){
 			if(hdr_T){
 				if(!hdr_T->repeat_fields){
 					hdr_T->repeat_fields = tsk_list_create();
 				}
 				tsk_list_push_back_data(hdr_T->repeat_fields, (void**)&header);
 			}
 			else{
 				tsdp_message_add_header(sdp_msg, header);
 				tsk_object_unref(header);
 			}
 		}
 	}
 	
 	action parse_header_S{
 		if((header = (tsdp_header_t*)tsdp_header_S_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 	
 	action parse_header_T{
 		if((hdr_T = tsdp_header_T_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, TSDP_HEADER(hdr_T));
 			hdr_T = tsk_object_unref(hdr_T);
 		}
 	}
 
 	action parse_header_U{
 		if((header = (tsdp_header_t*)tsdp_header_U_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 
 	action parse_header_V{
 		if((header = (tsdp_header_t*)tsdp_header_V_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 
 	action parse_header_Z{
 		if((header = (tsdp_header_t*)tsdp_header_Z_parse(tag_start, (p - tag_start)))){
 			tsdp_message_add_header(sdp_msg, header);
 			tsk_object_unref(header);
 		}
 	}
 
 	###########################################
 	#	Headers
 	###########################################
 
 	A = "a"i SP* "=" SP*<: any* %parse_header_A :>CRLF;
 	B = "b"i SP* "=" SP*<: any* %parse_header_B :>CRLF;
 	C = "c"i SP* "=" SP*<: any* %parse_header_C :>CRLF;
 	E = "e"i SP* "=" SP*<: any* %parse_header_E :>CRLF;
 	I = "i"i SP* "=" SP*<: any* %parse_header_I :>CRLF;
 	K = "k"i SP* "=" SP*<: any* %parse_header_K :>CRLF;
 	M = "m"i SP* "=" SP*<: any* %parse_header_M :>CRLF;
 	O = "o"i SP* "=" SP*<: any* %parse_header_O :>CRLF;
 	P = "p"i SP* "=" SP*<: any* %parse_header_P :>CRLF;
 	R = "r"i SP* "=" SP*<: any* %parse_header_R :>CRLF;
 	S = "s"i SP* "=" SP*<: any* %parse_header_S :>CRLF;
 	T = "t"i SP* "=" SP*<: any* %parse_header_T :>CRLF;
 	U = "u"i SP* "=" SP*<: any* %parse_header_U :>CRLF;
 	V = "v"i SP* "=" SP*<: any* %parse_header_V :>CRLF;
 	Z = "z"i SP* "=" SP*<: any* %parse_header_Z :>CRLF;
 
 	Dummy = alpha SP* "=" SP*<: any* %parse_header_Dummy :>CRLF;
 
 	Header = (A | B | C | E | I | K | M | O | P | R | S | T | U | V | Z)>tag >1 | (Dummy>tag) >0;
 
 
 	###########################################
 	#	Message
 	###########################################
 	SDP_message = Header*;
 
 	###########################################
 	#	Entry Point
 	###########################################
 	main := SDP_message;
 }%%
 
 TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
 /* Ragel data */
 %% write data;
 TSK_RAGEL_DISABLE_WARNINGS_END()
 
 tsdp_message_t* tsdp_message_parse(const void *input, tsk_size_t size)
 {
 	tsdp_message_t* sdp_msg = tsk_null;
 	const char* tag_start = tsk_null;
 	tsdp_header_t *header = tsk_null;
 	tsdp_header_T_t *hdr_T = tsk_null;
 	tsdp_header_M_t *hdr_M = tsk_null;
 
 	/* Ragel variables */
 	int cs = 0;
 	const char* p = input;
 	const char* pe = p + size;
 	const char* eof = tsk_null;
 
 	(void)(eof);
 
 	if(!input || !size){
 		TSK_DEBUG_ERROR("Null or empty buffer.");
 		goto bail;
 	}
 
 	if(!(sdp_msg = tsdp_message_create())){
 		goto bail;
 	}
 
 	TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
 	/* Ragel init */
 	%% write init;
 
 	/* Ragel execute */
 	%% write exec;
 	TSK_RAGEL_DISABLE_WARNINGS_END()
 
 	/* Check result */
 	if( cs < %%{ write first_final; }%% )
 	{
 		TSK_DEBUG_ERROR("Failed to parse SDP message.");
 		TSK_OBJECT_SAFE_FREE(sdp_msg);
 		goto bail;
 	}
 	
 bail:
 	return sdp_msg;
 }