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; } } }
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); }
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; }
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); }
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; }
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; } }