Beispiel #1
0
void MCArraysDoIntersect(MCExecContext& ctxt, MCArrayRef p_dst_array, MCArrayRef p_src_array, bool p_recursive)
{
	MCNameRef t_key;
	MCValueRef t_src_value;
    MCValueRef t_dst_value;
	uintptr_t t_iterator;
	t_iterator = 0;
    
    bool t_is_array;
    
	while(MCArrayIterate(p_dst_array, t_iterator, t_key, t_dst_value))
	{
		if (MCArrayFetchValue(p_src_array, ctxt . GetCaseSensitive(), t_key, t_src_value))
        {
            if (p_recursive && MCValueIsArray(t_dst_value) && MCValueIsArray(t_src_value))
            {
                MCArraysExecIntersectRecursive(ctxt, (MCArrayRef)t_dst_value, (MCArrayRef)t_src_value);
                if (ctxt . HasError())
                    return;
            }
			continue;
        }
        
		if (!MCArrayRemoveValue(p_dst_array, ctxt . GetCaseSensitive(), t_key))
		{
			ctxt . Throw();
			return;
		}
	}
}
Beispiel #2
0
void MCArraysExecCombineAsSet(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef& r_string)
{
	// String into which the combined keys are accumulated
    MCAutoStringRef t_string;
    
    // The array keys are not added in any particular order
    MCNameRef t_key;
    MCValueRef t_value_ignored;
    uintptr_t t_iterator = 0;
    while (MCArrayIterate(p_array, t_iterator, t_key, t_value_ignored))
    {
        bool t_success;
        t_success = true;
        if (*t_string == nil)
            t_success = MCStringMutableCopy(MCNameGetString(t_key), &t_string);
        else
            t_success = MCStringAppendFormat(*t_string, "%@%@", p_element_delimiter, t_key);
        
        if (!t_success)
        {
            ctxt . Throw();
            return;
        }
    }
    
    MCStringCopy(*t_string, r_string);
}
Beispiel #3
0
	bool createwidget(MCNameRef p_kind, MCArrayRef p_properties)
	{
		if (m_widget != nil)
			return true;
		
		m_widget = new (nothrow) MCWidget();
		if (m_widget == nil)
			return MCErrorThrowOutOfMemory();
		
        m_widget->setparent(this);
		m_widget->bind(p_kind, nil);
		m_widget->attach(OP_NONE, false);
        
		MCExecContext ctxt(MCdefaultstackptr, nil, nil);
		uintptr_t t_iter;
		t_iter = 0;
		
		MCNameRef t_key;
		MCValueRef t_value;
		
		while (MCArrayIterate(p_properties, t_iter, t_key, t_value))
		{
			MCEngineSetPropertyOfObject(ctxt, MCNameGetString(t_key), m_widget, 0, t_value);
			if (MCErrorIsPending())
				return false;
		}
		
		return true;
	}
Beispiel #4
0
void MCArraysExecSplitAsSet(MCExecContext& ctxt, MCStringRef p_string, MCStringRef p_element_delimiter, MCArrayRef& r_array)
{
	// Split the incoming string into its components
    MCAutoArrayRef t_keys;
    if (!MCStringSplit(p_string, p_element_delimiter, nil, ctxt . GetStringComparisonType(), &t_keys))
    {
        ctxt . Throw();
        return;
    }
    
    // The new array, with keys equal to the components of the string
    MCAutoArrayRef t_array;
    if (!MCArrayCreateMutable(&t_array))
    {
        ctxt . Throw();
        return;
    }
    
    MCNameRef t_key_ignored;
    MCValueRef t_value;
    uintptr_t t_iterator = 0;
    while (MCArrayIterate(*t_keys, t_iterator, t_key_ignored, t_value))
    {
        // The value stored at each key is a boolean "true"
        MCNewAutoNameRef t_keyname;
        if (!ctxt . ConvertToName(t_value, &t_keyname)
            || !MCArrayStoreValue(*t_array, ctxt . GetCaseSensitive(), *t_keyname, kMCTrue))
        {
            ctxt . Throw();
            return;
        }
        
    }
    
    MCArrayCopy(*t_array, r_array);
}
Beispiel #5
0
bool MCArraysCopyExtents(MCArrayRef self, array_extent_t*& r_extents, uindex_t& r_count)
{
	uintptr_t t_index = 0;
	MCNameRef t_key;
	MCValueRef t_value;

	bool t_has_extents = false;
	uindex_t t_dimensions = 0;
	MCAutoArray<array_extent_t> t_extents;

	while (MCArrayIterate(self, t_index, t_key, t_value))
	{
		MCAutoPointer<index_t> t_indexes;
		uindex_t t_index_count;
		bool t_all_integers;
		if (!MCArraysSplitIndexes(t_key, &t_indexes, t_index_count, t_all_integers))
			return false;

		if (!t_all_integers || t_index_count == 0)
		{
			t_has_extents = false;
			break;
		}

		if (!t_has_extents)
		{
			t_dimensions = t_index_count;

			t_has_extents = true;
			
			if (!t_extents.New(t_dimensions))
				return false;
			for (uindex_t i = 0; i < t_dimensions; i++)
				t_extents[i].min = t_extents[i].max = (*t_indexes)[i];
		}
		else
		{
			if (t_dimensions != t_index_count)
			{
				t_has_extents = false;
				break;
			}
			for (uindex_t i = 0; i < t_dimensions; i++)
			{
				integer_t t_number = (*t_indexes)[i];
				if (t_number > t_extents[i].max)
					t_extents[i].max = t_number;
				if (t_number < t_extents[i].min)
					t_extents[i].min = t_number;
			}
		}
	}

	if (!t_has_extents)
	{
		r_extents = nil;
		r_count = 0;
		return true;
	}

	t_extents.Take(r_extents, r_count);
	return true;
}
Beispiel #6
0
void MCKeywordsExecRepeatFor(MCExecContext& ctxt, MCStatement *statements, MCExpression *endcond, MCVarref *loopvar, File_unit each, uint2 line, uint2 pos)
{
    MCAutoArrayRef t_array;
    MCAutoStringRef t_string;
    MCAutoDataRef t_data;
    MCRange t_chunk_range;
    t_chunk_range = MCRangeMake(0,0);
    uindex_t t_length = 0;
    MCAutoValueRef t_condition;
	MCNameRef t_key;
	MCValueRef t_value;
	uintptr_t t_iterator;
    // SN2015-06-15: [[ Bug 15457 ]] The index can be a negative index.
    index_t t_sequenced_iterator;
    const byte_t *t_data_ptr;
    
    MCAutoPointer<MCTextChunkIterator> tci;
    
    if (!ctxt . TryToEvaluateExpression(endcond, line, pos, EE_REPEAT_BADFORCOND, &t_condition))
        return;
    
    bool t_sequence_array;
    t_sequence_array = false;

    if (each == FU_ELEMENT || each == FU_KEY)
    {
        if (!ctxt . ConvertToArray(*t_condition, &t_array))
            return;
        
        // SN-2015-06-15: [[ Bug 15457 ]] If this is a numerical array, do
        //  it in order - even if it does not start at 1
        if (each == FU_ELEMENT && MCArrayIsNumericSequence(*t_array, t_sequenced_iterator))
        {
            t_sequence_array = true;
            if (!MCArrayFetchValueAtIndex(*t_array, t_sequenced_iterator, t_value))
                return;
        }
        else
        {
            t_iterator = 0;
            if (!MCArrayIterate(*t_array, t_iterator, t_key, t_value))
                return;
        }
    }
    else if (each == FU_BYTE)
    {
        if (!ctxt . ConvertToData(*t_condition, &t_data))
            return;
        
        t_length = MCDataGetLength(*t_data);
        t_data_ptr = MCDataGetBytePtr(*t_data);
    }
    else
    {
        if (!ctxt . ConvertToString(*t_condition, &t_string))
            return;
        
        switch (each)
        {
            case FU_LINE:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_LINE);
                break;
            case FU_PARAGRAPH:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_PARAGRAPH);
                break;
            case FU_SENTENCE:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_SENTENCE);
                break;
            case FU_ITEM:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_ITEM);
                break;
            case FU_WORD:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_WORD);
                break;
            case FU_TRUEWORD:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_TRUEWORD);
                break;
            case FU_TOKEN:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_TOKEN);
                break;
            case FU_CODEPOINT:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_CODEPOINT);
                break;
            case FU_CODEUNIT:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_CODEUNIT);
                break;
            case FU_CHARACTER:
            default:
                tci = MCStringsTextChunkIteratorCreate(ctxt, *t_string, CT_CHARACTER);
                break;
        } 
    }
    
    bool done;
    done = false;
    
    bool endnext;
    endnext = false;
    
    bool t_found;
    t_found = false;
    
    while (!done)
    {
        MCAutoStringRef t_unit;
        MCAutoDataRef t_byte;
        switch (each)
        {
            case FU_KEY:
            {
                loopvar -> set(ctxt, t_key);
                if (!MCArrayIterate(*t_array, t_iterator, t_key, t_value))
                    endnext = true;
            }
            break;
                
            case FU_ELEMENT:
            {
                loopvar -> set(ctxt, t_value);
                // SN-2015-06-15: [[ Bug 15457 ]] Sequenced, numeric arrays
                //  have their own iterator
                if (t_sequence_array)
                {
                    if (!MCArrayFetchValueAtIndex(*t_array, ++t_sequenced_iterator, t_value))
                        endnext = true;
                }
                else
                {
                    if (!MCArrayIterate(*t_array, t_iterator, t_key, t_value))
                        endnext = true;
                }
            }
            break;
            
            case FU_BYTE:
            {
                // SN-2014-04-14 [[ Bug 12184 ]] If we have no data at all, we don't want to start the loop
                if (t_length)
                {
                    MCDataCreateWithBytes(t_data_ptr++, 1, &t_byte);
                    
                    endnext = (--t_length) == 0;
                }
                else
                    done = true;
            }
            break;
                
            default:
            {
                t_found = MCStringsTextChunkIteratorNext(ctxt, *tci);
                endnext = tci -> IsExhausted();
                
                if (!t_found)
                {
                    t_unit = kMCEmptyString;
                    done = true;
                }
                else
                    tci -> CopyString(&t_unit);
            }
            break;
        }
        // MW-2010-12-15: [[ Bug 9218 ]] Added KEY to the type of repeat that already
        //   copies the value.
        // MW-2011-02-08: [[ Bug ]] Make sure we don't use 't_unit' if the repeat type is 'key' or
        //   'element'.
        // Set the loop variable to whatever the value was in the last iteration.
        if (each == FU_BYTE)
        {
            // SN-2014-04-14 [[ Bug 12184 ]] We don't need to set anything since we are not going in the loop
            if (!done)
                loopvar -> set(ctxt, *t_byte);
        }
        else if (each != FU_ELEMENT && each != FU_KEY)
            loopvar -> set(ctxt, *t_unit);
        
        if (!done)
            MCKeywordsExecuteRepeatStatements(ctxt, statements, line, pos, done);
        
        if (endnext)
        {
            // Reset the loop variable to whatever the value was in the last iteration.
            if (loopvar != nil)
            {
                if (each == FU_BYTE)
                    loopvar -> set(ctxt, *t_byte);
                else if (each != FU_ELEMENT && each != FU_KEY)
                    loopvar -> set(ctxt, *t_unit);
            }
        }
        
        done = done || endnext;
    }
}