Beispiel #1
0
Exec_stat MCSort::sort_container(MCExecPoint &p_exec_point, Chunk_term p_type, Sort_type p_direction, Sort_type p_form, MCExpression *p_by)
{
	MCSortnode *t_items;
	uint4 t_item_count;
	t_item_count = 0;

	// If sorting items of the container, then we use the current itemDelimiter to split each item,
	// all other forms of search default to the lineDelimiter for now. Note that this is a slight
	// change of behavior as previously sorting containers by line ignored the lineDelimiter and
	// always delimited by ascii 10.
	char t_delimiter;
	if (p_type == CT_ITEM)
		t_delimiter = p_exec_point . getitemdel();
	else
		t_delimiter = p_exec_point . getlinedel();

	if (t_delimiter == '\0')
		return ES_NORMAL;

	// Calculate the number of items we need to sort, store this in t_item_count.
	uint4 t_item_size;
	t_item_size = p_exec_point . getsvalue() . getlength();

	char *t_item_text;
	t_item_text = p_exec_point . getsvalue() . clone();

	char *t_string_pointer;
	t_string_pointer = t_item_text;

	char *t_end_pointer;
	bool t_trailing_delim = false;
	while ((t_end_pointer = strchr(t_string_pointer, t_delimiter)) != NULL)
	{
		// knock out last delim for lines with a trailing return char
		if (p_type != CT_ITEM && t_end_pointer[1] == '\0')
		{
			t_end_pointer[0] = '\0';
			t_trailing_delim = true;
		}
		else
			t_item_count++;
		t_string_pointer = t_end_pointer + 1;
	}

	// OK-2008-12-11: [[Bug 7503]] - If there are 0 items in the string, don't carry out the search,
	// this keeps the behavior consistent with previous versions of Revolution.
	if (t_item_count < 1)
	{
		delete t_item_text;
		return ES_NORMAL;
	}

	// Now we know the item count, we can allocate an array of MCSortnodes to store them.
	t_items = new MCSortnode[t_item_count + 1];
	t_item_count = 0;
	t_string_pointer = t_item_text;

	// Next, populate the MCSortnodes with all the items to be sorted
	MCString t_string;
	do
	{
		if ((t_end_pointer = strchr(t_string_pointer, t_delimiter)) != NULL)
		{
			*t_end_pointer++ = '\0';
			t_string . set(t_string_pointer, t_end_pointer - t_string_pointer - 1);
		}
		else
			t_string . set(t_string_pointer, strlen(t_string_pointer));

		MCExecPoint t_exec_point2(p_exec_point);
		additem(t_exec_point2, t_items, t_item_count, p_form, t_string, p_by);

		t_items[t_item_count - 1] . data = (void *)t_string_pointer;
		t_string_pointer = t_end_pointer;
	}
	while (t_end_pointer != NULL);

	// Sort the array
	MCU_sort(t_items, t_item_count, p_direction, p_form);

	// Build the output string
	char *t_output;
	t_output = new char[t_item_size + 1];
	*t_output = '\0';
	
	uint4 t_length;
	t_length = 0;

	for (unsigned int i = 0; i < t_item_count; i++)
	{
		uint4 t_item_length;
		t_item_length = strlen((const char *)t_items[i] . data);
		strncpy(&t_output[t_length], (const char *)t_items[i] . data, t_item_length);
		t_length = t_length + t_item_length;

		if ((p_form == ST_INTERNATIONAL || p_form == ST_TEXT) && (!p_exec_point . getcasesensitive() || p_by != NULL))
			delete t_items[i] . svalue;

		if (t_trailing_delim || i < t_item_count - 1)
			t_output[t_length++] = t_delimiter;
	}
	t_output[t_length] = '\0';

	p_exec_point . grabbuffer(t_output, t_length);

	delete t_item_text;
	delete t_items;
	return ES_NORMAL;
}
Beispiel #2
0
Exec_stat MCFunction::evalparams(Functions func, MCParameter *params,
                                 MCExecPoint &ep)
{
	uint4 nparams = 0;
	real8 n, tn, oldn;
	n = oldn = 0.0;
	MCSortnode *mditems = NULL;
	// JS-2013-06-19: [[ StatsFunctions ]] Support for new stats functions based on arithmeticMean
	if (func == F_AVG_DEV || func == F_POP_STD_DEV || func == F_POP_VARIANCE || func == F_SMP_STD_DEV || func == F_SMP_VARIANCE)
	{ //use recursion to get average first
		if (evalparams(F_ARI_MEAN, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	// JS-2013-06-19: [[ StatsFunctions ]] Support for geometricMean
	if (func == F_GEO_MEAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	if (func == F_MEDIAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		mditems = new MCSortnode[(uint4)ep.getnvalue()];
	}
	if (params != NULL && params->getnext() == NULL)
	{
		if (params->eval(ep) != ES_NORMAL)
		{
			MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
			return ES_ERROR;
		}
		if (ep.getformat() == VF_ARRAY)
		{
			if (ep.getarray() -> is_array() && ep.getarray()->get_array()->dofunc(ep, func, nparams, n, oldn, mditems) != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
		}
		else
		{
			MCString s(ep.getsvalue());
			uint4 length = s.getlength();
			const char *sptr = s.getstring();
			MCU_skip_spaces(sptr, length);
			while (length != 0)
			{
				s.setstring(sptr);
				if (!MCU_strchr(sptr, length, ','))
				{
					s.setlength(length);
					length = 0;
				}
				else
				{
					s.setlength(sptr - s.getstring());
					MCU_skip_char(sptr, length);
					MCU_skip_spaces(sptr, length);
				}
				if (s.getlength() == 0)
					tn = 0.0;
				else
					if (!MCU_stor8(s, tn))
					{
						MCeerror->add
						(EE_FUNCTION_NAN, 0, 0, s);
						return ES_ERROR;
					}
				MCU_dofunc(func, nparams, n, tn, oldn, mditems);
			}
		}
	}
	else
	{
		MCParameter *tparam = params;
		while (tparam != NULL)
		{
			if (tparam->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
			MCU_dofunc(func, nparams, n, ep.getnvalue(), oldn, mditems);
			tparam = tparam->getnext();
		}
	}
	
	if (nparams != 0)
		switch (func)
	{
		// JS-2013-06-19: [[ StatsFunctions ]] Support for arithmeticMean (was average)
		case F_ARI_MEAN:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for averageDeviation
		case F_AVG_DEV:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for harmonicMean
		case F_HAR_MEAN:
			n = nparams/n;
			break;
		case F_MEDIAN:
			{
				uint4 toffset;
				MCU_sort(mditems, nparams, ST_ASCENDING, ST_NUMERIC);
				toffset = (nparams + 1)/2 - 1;
				if ((nparams % 2) != 0) //odd
					n = mditems[toffset].nvalue;
				else //even average 2 closest values
					n = (mditems[toffset].nvalue + mditems[toffset+1].nvalue)/2;
				break;
			}
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationStandardDeviation
		case F_POP_STD_DEV:
			n = sqrt(n/nparams);
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationVariance
		case F_POP_VARIANCE:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleStandardDeviation (was stdDev)
		case F_SMP_STD_DEV:
			n = sqrt(n/(nparams - 1));
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleVariance
		case F_SMP_VARIANCE:
			n /= nparams - 1;
			break;
		case F_UNDEFINED:
			n = nparams;
			break;
		default:
			break;
		}
	ep.setnvalue(n);
	delete mditems;
	return ES_NORMAL;
}