doubango/tinyMEDIA/ragel/tmedia_imageattr.rl
c732d49e
 /*
 * Copyright (C) 2012-2015 Doubango Telecom <http://www.doubango.org>
 *	
 * 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 tmedia_imageattr.c
  * @brief 'image-attr' parser as per RFC 6236
  */
 #include "tinymedia/tmedia_imageattr.h"
 
 #include "tsk_ragel_state.h"
 #include "tsk_debug.h"
 
 #include <stdlib.h>
 
 /***********************************
 *	Ragel state machine.
 */
 %%{
 	machine tmedia_machine_imageattr;
 
 	# Includes
 	include tmedia_machine_utils "./ragel/tmedia_machine_utils.rl";
 
 	action tag{
 		tag_start = p;
 	}
 
 	action is_send{
 		sets = &self->send.sets[0];
 		sets_count = &self->send.count;
 		*sets_count = 0;
 	}
 
 	action is_recv{
 		sets = &self->recv.sets[0];
 		sets_count = &self->recv.count;
 		*sets_count = 0;
 	}
 
 	action is_xrange{
 		xyrange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].xrange : tsk_null;
 	}
 	action is_yrange{
 		xyrange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].yrange : tsk_null;
 	}
 	action set_parsed{
 		if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) (*sets_count)++;
 	}
 	action set_is_not_range{
 		if(xyrange) xyrange->is_range = 0;
 	}
 	action set_is_range{
 		if(xyrange) xyrange->is_range = 1;
 	}
 	action parse_xyvalue_range_start{
 		if(xyrange)xyrange->range.start = atoi(tag_start);
 	}
 	action parse_xyvalue_range_step{
 		if(xyrange)xyrange->range.step = atoi(tag_start);
 	}
 	action parse_xyvalue_range_end{
 		if(xyrange)xyrange->range.end = atoi(tag_start);
 	}
 	action parse_xyvalue_array_value{
 		if(xyrange && xyrange->array.count < TMEDIA_imageattr_ARRAY_MAX_SIZE){
 			xyrange->array.values[xyrange->array.count++] = atoi(tag_start);
 		}
 	}
 	action set_parse_qvalue{
 		if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE){
 			sets[*sets_count].qvalue = atof(tag_start);
 		}
 	}
 
 	action srange_is_array{
 		if(srange) srange->is_range = 0;
 	}
 	action srange_is_not_array{
 		if(srange) srange->is_range = 1;
 	}
 	action start_srange{
 		srange = (*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) ? &sets[*sets_count].srange : tsk_null;
 	}
 	action parse_srange_array_value{
 		if(srange && srange->array.count < TMEDIA_imageattr_ARRAY_MAX_SIZE){
 			srange->array.values[srange->array.count++] = atof(tag_start);
 		}
 	}
 	action parse_srange_range_start{
 		if(srange) srange->range.start = atof(tag_start);
 	}
 	action parse_srange_range_end{
 		if(srange) srange->range.end = atof(tag_start);
 	}
 
 	action parse_prange_start{
 		if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) sets[*sets_count].prange.start = atof(tag_start);
 	}
 	action parse_prange_end{
 		if(*sets_count < TMEDIA_imageattr_ARRAY_MAX_SIZE) sets[*sets_count].prange.end = atof(tag_start), sets[*sets_count].prange.is_present = 1;
 	}
 
 	PT = DIGIT+ | "*";
 	onetonine = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
 	xyvalue = (onetonine DIGIT{,5});
 	step = xyvalue;
 	xyrange = ( "[" xyvalue>tag %parse_xyvalue_range_start ":" ( step>tag %parse_xyvalue_range_step ":" )? xyvalue>tag %parse_xyvalue_range_end "]" )%set_is_range | ( "[" xyvalue>tag %parse_xyvalue_array_value ( "," xyvalue>tag %parse_xyvalue_array_value )+ "]" )%set_is_not_range | xyvalue%set_is_not_range>tag %parse_xyvalue_array_value;
 	spvalue = ( "0" "." onetonine DIGIT{,3} ) | ( onetonine "." DIGIT{1,4} );
 	srange = (( "[" spvalue>tag %parse_srange_array_value ( "," spvalue>tag %parse_srange_array_value )+ "]" )%srange_is_array | ( "[" spvalue>tag %parse_srange_range_start "-" spvalue>tag %parse_srange_range_end "]" )%srange_is_not_array | spvalue>tag %parse_srange_array_value %srange_is_array)>start_srange;
 	prange = ( "[" spvalue>tag %parse_prange_start "-" spvalue>tag %parse_prange_end "]" );
 	_qvalue = (( "0" "." DIGIT{1,2} ) | ( "1" "." "0"{1,2} ))>tag %set_parse_qvalue; #qvalue collision
 	key_value = ( "sar="i srange ) | ( "par="i prange ) | ( "q="i _qvalue );
 	set = ("[" "x="i xyrange>is_xrange "," "y="i xyrange>is_yrange ( "," key_value )* "]")%set_parsed;
 	attr_list = ( set ( WSP+ set )* ) | "*";
 	imageattr = ( WSP* ( "send"i%is_send | "recv"i%is_recv ) WSP+ attr_list ){1,2};
 
 	# Entry point
 	main:= imageattr;
 }%%
 
 static int tmedia_imageattr_reset(tmedia_imageattr_xt* self)
 {
 	if(self){
 		tsk_size_t i;
 		memset(self, 0, sizeof(*self));
 		for(i = 0; i < TMEDIA_imageattr_ARRAY_MAX_SIZE; ++i){
 			self->send.sets[i].qvalue = 0.5;
 			self->recv.sets[i].qvalue = 0.5;
 		}
 		return 0;
 	}
 	TSK_DEBUG_ERROR("Invalid parameter");
 	return -1;
 }
 
 int tmedia_imageattr_parse(tmedia_imageattr_xt* self, const void* in_data, tsk_size_t in_size)
 {
 	int cs = 0;
 	const char *p = in_data;
 	const char *pe = p + in_size;
 	const char *eof = pe;
 	
 	const char *tag_start = tsk_null;
 
 	tmedia_imageattr_set_xt* sets = tsk_null;
 	tsk_size_t* sets_count = tsk_null;
 	tmedia_imageattr_xyrange_xt* xyrange = tsk_null;
 	tmedia_imageattr_srange_xt* srange = tsk_null;
 
 	TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
 	%%write data;
 	(void)(eof);
 	(void)(tmedia_machine_imageattr_first_final);
 	(void)(tmedia_machine_imageattr_error);
 	(void)(tmedia_machine_imageattr_en_main);
 	%%write init;
 	tmedia_imageattr_reset(self);
 	%%write exec;
 	TSK_RAGEL_DISABLE_WARNINGS_END()
 
 	if( cs < %%{ write first_final; }%% ){
 		TSK_DEBUG_ERROR("Parsing failed to parse image-attr=%s", (char*)in_data);
 		return -1;
 	}
 	
 	return 0;
 }