Skip to content

Commit 0a02d3c

Browse files
[[ RefactorSyntax ]] Fixed combine by row/combine by column
1 parent e4da775 commit 0a02d3c

3 files changed

Lines changed: 170 additions & 15 deletions

File tree

engine/src/cmdsm.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,9 +1205,9 @@ void MCArrayOp::exec_ctxt(MCExecContext &ctxt)
12051205
MCAutoStringRef t_string;
12061206
if (form == FORM_NONE)
12071207
{
1208-
if (chunk == TYPE_COLUMN)
1209-
MCArraysExecCombineByColumn(ctxt, *t_array, &t_string);
1210-
else
1208+
if (chunk == TYPE_COLUMN || chunk == TYPE_ROW)
1209+
MCArraysExecCombineByRowOrColumn(ctxt, *t_array, chunk == TYPE_ROW, &t_string);
1210+
else
12111211
MCArraysExecCombine(ctxt, *t_array, *t_element_del, *t_key_del, &t_string);
12121212
}
12131213
else if (form == FORM_SET)
@@ -1258,8 +1258,8 @@ void MCArrayOp::compile(MCSyntaxFactoryRef ctxt)
12581258
{
12591259
if (form == FORM_NONE)
12601260
{
1261-
if (mode == TYPE_COLUMN)
1262-
MCSyntaxFactoryExecMethodWithArgs(ctxt, kMCArraysExecCombineByColumnMethodInfo, 0, 0);
1261+
if (mode == TYPE_COLUMN || mode == TYPE_ROW)
1262+
MCSyntaxFactoryExecMethodWithArgs(ctxt, kMCArraysExecCombineByRowOrColumnMethodInfo, 0, 1, 0);
12631263
else
12641264
MCSyntaxFactoryExecMethodWithArgs(ctxt, kMCArraysExecCombineMethodInfo, 0, 1, 2, 0);
12651265
}

engine/src/exec-array.cpp

Lines changed: 163 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
3434
MC_EXEC_DEFINE_EVAL_METHOD(Arrays, Keys, 2)
3535
MC_EXEC_DEFINE_EVAL_METHOD(Arrays, Extents, 2)
3636
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, Combine, 4)
37-
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, CombineByRow, 2)
38-
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, CombineByColumn, 2)
37+
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, CombineByRowOrColumn, 3)
3938
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, CombineAsSet, 3)
4039
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, Split, 4)
4140
MC_EXEC_DEFINE_EXEC_METHOD(Arrays, SplitByRow, 2)
@@ -72,7 +71,7 @@ struct array_element_t
7271

7372
struct combine_array_t
7473
{
75-
uindex_t index;
74+
uindex_t index;
7675
array_element_t *elements;
7776
};
7877

@@ -94,6 +93,56 @@ static int compare_array_element(const void *a, const void *b)
9493
return MCStringCompareTo(MCNameGetString(t_left -> key), MCNameGetString(t_right -> key), kMCStringOptionCompareExact);
9594
}
9695

96+
////////////////////////////////////////////////////////////////////////////////
97+
98+
// combine by row or column expects an integer-indexed array
99+
struct array_int_indexed_element_t
100+
{
101+
index_t key;
102+
MCValueRef value;
103+
};
104+
105+
struct combine_int_indexed_array_t
106+
{
107+
uindex_t index;
108+
array_int_indexed_element_t *elements;
109+
MCExecContext* converter;
110+
};
111+
112+
static bool list_int_indexed_array_elements(void *p_context, MCArrayRef p_array, MCNameRef p_key, MCValueRef p_value)
113+
{
114+
combine_int_indexed_array_t *ctxt;
115+
ctxt = (combine_int_indexed_array_t *)p_context;
116+
117+
MCAutoNumberRef t_key;
118+
if (ctxt -> converter -> ConvertToNumber(MCNameGetString(p_key), &t_key))
119+
{
120+
index_t t_key_num = MCNumberFetchAsInteger(*t_key);
121+
122+
if (t_key_num < 1) // Invalid index
123+
return false;
124+
125+
ctxt -> elements[ctxt -> index] . key = t_key_num;
126+
ctxt -> elements[ctxt -> index] . value = p_value;
127+
++(ctxt -> index);
128+
129+
return true;
130+
}
131+
else
132+
return false;
133+
}
134+
135+
static int compare_int_indexed_elements(const void *a, const void* b)
136+
{
137+
const array_int_indexed_element_t *t_left, *t_right;
138+
t_left = (const array_int_indexed_element_t *)a;
139+
t_right = (const array_int_indexed_element_t *)b;
140+
141+
return (t_left -> key - t_right -> key < 0) ? -1 : (t_left -> key != t_right -> key ? 1 : 0);
142+
}
143+
144+
////////////////////////////////////////////////////////////////////////////////
145+
97146
void MCArraysExecCombine(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef p_key_delimiter, MCStringRef& r_string)
98147
{
99148
bool t_success;
@@ -107,14 +156,14 @@ void MCArraysExecCombine(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_
107156
t_success = MCStringCreateMutable(0, &t_string);
108157

109158
combine_array_t t_lisctxt;
110-
t_lisctxt . elements = nil;
159+
t_lisctxt . elements = nil;
111160
if (t_success)
112161
t_success = MCMemoryNewArray(t_count, t_lisctxt . elements);
113162

114163
if (t_success)
115164
{
116-
t_lisctxt . index = 0;
117-
MCArrayApply(p_array, list_array_elements, &t_lisctxt);
165+
t_lisctxt . index = 0;
166+
MCArrayApply(p_array, list_array_elements, &t_lisctxt);
118167
qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_array_element);
119168
for(uindex_t i = 0; i < t_count; i++)
120169
{
@@ -151,9 +200,115 @@ void MCArraysExecCombine(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_
151200
ctxt . Throw();
152201
}
153202

154-
void MCArraysExecCombineByColumn(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef& r_string)
203+
// Should be removed when 'combine by row' and 'combine by column' only differs by the delimiter used,
204+
// not by the way the array is handled - any index is fine for combine by row
205+
void MCArraysExecCombineByRow(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef &r_string)
155206
{
156-
ctxt . Unimplemented();
207+
MCAutoListRef t_list;
208+
MCListCreateMutable(ctxt . GetRowDelimiter(), &t_list);
209+
210+
uindex_t t_count = MCArrayGetCount(p_array);
211+
combine_array_t t_lisctxt;
212+
bool t_success;
213+
214+
t_lisctxt . elements = nil;
215+
t_lisctxt . index = 0;
216+
t_success = MCMemoryNewArray(t_count, t_lisctxt . elements);
217+
218+
if (t_success)
219+
{
220+
MCArrayApply(p_array, list_array_elements, &t_lisctxt);
221+
qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_array_element);
222+
223+
for (int i = 0; i < t_count && t_success; ++i)
224+
{
225+
MCAutoStringRef t_string;
226+
if (ctxt . ConvertToString(t_lisctxt . elements[i] . value, &t_string))
227+
t_success = MCListAppend(*t_list, *t_string);
228+
else
229+
t_success = false;
230+
}
231+
232+
MCMemoryDeleteArray(t_lisctxt . elements);
233+
}
234+
235+
if (t_success && MCListCopyAsString(*t_list, r_string))
236+
return;
237+
238+
ctxt . Throw();
239+
}
240+
241+
void MCArraysExecCombineByRowOrColumn(MCExecContext& ctxt, MCArrayRef p_array, bool p_is_row, MCStringRef &r_string)
242+
{
243+
if (p_is_row)
244+
{
245+
// Temporarily buggy output for 'combine by row'
246+
MCArraysExecCombineByRow(ctxt, p_array, r_string);
247+
return;
248+
}
249+
250+
char_t t_delimiter;
251+
if (p_is_row)
252+
t_delimiter = ctxt . GetRowDelimiter();
253+
else
254+
t_delimiter = ctxt . GetColumnDelimiter();
255+
256+
MCAutoListRef t_list;
257+
MCListCreateMutable(t_delimiter, &t_list);
258+
259+
uindex_t t_count = MCArrayGetCount(p_array);
260+
combine_int_indexed_array_t t_lisctxt;
261+
bool t_success;
262+
263+
t_lisctxt . elements = nil;
264+
t_lisctxt . index = 0;
265+
t_lisctxt . converter = &ctxt;
266+
t_success = MCMemoryNewArray(t_count, t_lisctxt . elements);
267+
268+
if (t_success)
269+
{
270+
if (MCArrayApply(p_array, list_int_indexed_array_elements, &t_lisctxt))
271+
{
272+
bool t_valid_keys;
273+
274+
qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_int_indexed_elements);
275+
276+
// Combine by row/column is only valid if all the indices are consecutive numbers
277+
// Otherwise, an empty string is returned - no error
278+
index_t t_last_index;
279+
t_valid_keys = true;
280+
t_last_index = 0;
281+
for (int i = 0; i < t_count && t_valid_keys; ++i)
282+
{
283+
if (!t_last_index)
284+
t_last_index = t_lisctxt . elements[i] . key;
285+
else
286+
t_valid_keys = ++t_last_index == t_lisctxt . elements[i] . key;
287+
}
288+
289+
if (t_valid_keys)
290+
{
291+
for (int i = 0; i < t_count && t_success; ++i)
292+
{
293+
MCAutoStringRef t_string;
294+
295+
if (t_lisctxt . elements[i] . key == 0) // The index 0 is ignored
296+
continue;
297+
298+
if (ctxt . ConvertToString(t_lisctxt . elements[i] . value, &t_string))
299+
t_success = MCListAppend(*t_list, *t_string);
300+
else
301+
t_success = false;
302+
}
303+
}
304+
}
305+
MCMemoryDeleteArray(t_lisctxt . elements);
306+
}
307+
308+
if (t_success && MCListCopyAsString(*t_list, r_string))
309+
return;
310+
311+
ctxt . Throw();
157312
}
158313

159314
void MCArraysExecCombineAsSet(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef& r_string)

engine/src/exec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,7 +1742,7 @@ void MCLogicEvalIsNotABoolean(MCExecContext& ctxt, MCValueRef p_value, bool& r_r
17421742
extern MCExecMethodInfo *kMCArraysEvalKeysMethodInfo;
17431743
extern MCExecMethodInfo *kMCArraysEvalExtentsMethodInfo;
17441744
extern MCExecMethodInfo *kMCArraysExecCombineMethodInfo;
1745-
extern MCExecMethodInfo *kMCArraysExecCombineByColumnMethodInfo;
1745+
extern MCExecMethodInfo *kMCArraysExecCombineByRowOrColumnMethodInfo;
17461746
extern MCExecMethodInfo *kMCArraysExecCombineAsSetMethodInfo;
17471747
extern MCExecMethodInfo *kMCArraysExecSplitMethodInfo;
17481748
extern MCExecMethodInfo *kMCArraysExecSplitByColumnMethodInfo;
@@ -1761,7 +1761,7 @@ extern MCExecMethodInfo *kMCArraysEvalIsNotAmongTheKeysOfMethodInfo;
17611761
void MCArraysEvalKeys(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef& r_string);
17621762
void MCArraysEvalExtents(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef& r_string);
17631763
void MCArraysExecCombine(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef p_key_delimiter, MCStringRef& r_string);
1764-
void MCArraysExecCombineByColumn(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef& r_string);
1764+
void MCArraysExecCombineByRowOrColumn(MCExecContext& ctxt, MCArrayRef p_array, bool p_is_row, MCStringRef &r_string);
17651765
void MCArraysExecCombineAsSet(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef& r_string);
17661766
void MCArraysExecSplit(MCExecContext& ctxt, MCStringRef p_string, MCStringRef p_element_delimiter, MCStringRef p_key_delimiter, MCArrayRef& r_array);
17671767
void MCArraysExecSplitByColumn(MCExecContext& ctxt, MCStringRef p_string, MCArrayRef& r_array);

0 commit comments

Comments
 (0)