Skip to content

Commit dda9294

Browse files
author
Fraser J. Gordon
committed
Make copying of an MCListRef actually work
1 parent 329c1c7 commit dda9294

2 files changed

Lines changed: 53 additions & 4 deletions

File tree

libfoundation/include/foundation.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,10 +1850,11 @@ bool MCListAppendNativeChars(MCListRef list, const char_t *chars, uindex_t char_
18501850
bool MCListAppendFormat(MCListRef list, const char *format, ...);
18511851

18521852
// Make an immutable copy of the list.
1853-
// Note that this method is fragile at the moment and should only be used to
1854-
// copy a list out of an autolistref that is about to be deallocated.
18551853
bool MCListCopy(MCListRef list, MCListRef& r_new_list);
18561854

1855+
// Makes an immutable copy of the list and release the list
1856+
bool MCListCopyAndRelease(MCListRef list, MCListRef& r_new_list);
1857+
18571858
// Make a copy of the list as a string.
18581859
bool MCListCopyAsString(MCListRef list, MCStringRef& r_string);
18591860

libfoundation/src/foundation-list.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,55 @@ bool MCListAppend(MCListRef self, MCValueRef p_value)
7575

7676
bool MCListCopy(MCListRef self, MCListRef& r_list)
7777
{
78-
r_list = MCValueRetain(self);
78+
MCAssert(self != nil);
79+
80+
// If we are immutable, just bump the reference count
81+
if (!self -> flags & kMCListFlagIsMutable)
82+
{
83+
r_list = MCValueRetain(self);
84+
return true;
85+
}
86+
87+
// Create a new list
88+
MCListRef t_new_list;
89+
if (!MCListCreateMutable(self -> delimiter, t_new_list))
90+
return false;
91+
92+
// Mark the new list as immutable
93+
t_new_list -> flags &= ~kMCListFlagIsMutable;
94+
95+
// Create an immutable copy of the list contents
96+
if (self -> buffer == nil)
97+
{
98+
t_new_list -> buffer = nil;
99+
}
100+
else if (!MCStringCopy(self -> buffer, t_new_list -> buffer))
101+
{
102+
MCValueRelease(t_new_list);
103+
return false;
104+
}
105+
106+
r_list = t_new_list;
79107
return true;
80108
}
81109

110+
bool MCListCopyAndRelease(MCListRef self, MCListRef& r_list)
111+
{
112+
// If there are no other references, just clear the mutable flag
113+
if (self -> references == 1)
114+
{
115+
self -> flags &= ~kMCListFlagIsMutable;
116+
r_list = self;
117+
return true;
118+
}
119+
120+
// Otherwise perform a normal copy operation followed by a release
121+
if (!MCListCopy(self, r_list))
122+
return false;
123+
MCValueRelease(self);
124+
return true;
125+
}
126+
82127
bool MCListCopyAsString(MCListRef self, MCStringRef& r_string)
83128
{
84129
MCStringRef t_string;
@@ -188,7 +233,10 @@ bool __MCListCopyDescription(__MCList *self, MCStringRef& r_string)
188233

189234
bool __MCListImmutableCopy(__MCList *self, bool p_release, __MCList*& r_immutable_value)
190235
{
191-
return false;
236+
if (!p_release)
237+
return MCListCopy(self, r_immutable_value);
238+
239+
return MCListCopyAndRelease(self, r_immutable_value);
192240
}
193241

194242
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)