Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit e8011d3

Browse files
committed
[[misc-customtypes]] libfoundation: Check custom type func pointers before call
Some custom types may not wish to implement all function pointers in the corresponding `MCValueCustomCallbacks` structure -- for example, some custom types may not support mutability and thus may not implement a `mutable_copy` function. Furthermore, additional members may be added to `struct MCValueCustomCallbacks` over time, requiring every custom type to be adjusted unless the custom value support code can cope with NULL function pointers. This patch adds default implementations of all the functions defined in `struct MCValueCustomCallbacks`, and calls them for any type that leaves the corresponding function pointer as NULL.
1 parent fc7c5e7 commit e8011d3

File tree

5 files changed

+156
-10
lines changed

5 files changed

+156
-10
lines changed

libfoundation/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SOURCES= \
77
foundation-array.cpp \
88
foundation-bidi.cpp \
99
foundation-core.cpp \
10+
foundation-custom.cpp \
1011
foundation-data.cpp \
1112
foundation-debug.cpp \
1213
foundation-error.cpp \

libfoundation/include/foundation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,9 @@ enum
11181118
kMCValueCustomHeaderSize = sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uintptr_t)
11191119
};
11201120

1121+
/* If you add a new function pointer to this structure, don't forget
1122+
* to add a default implementation of the function to
1123+
* foundation-custom.cpp */
11211124
struct MCValueCustomCallbacks
11221125
{
11231126
bool is_singleton : 1;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* -*-c++-*-
2+
Copyright (C) 2003-2013 Runtime Revolution Ltd.
3+
4+
This file is part of LiveCode.
5+
6+
LiveCode is free software; you can redistribute it and/or modify it under
7+
the terms of the GNU General Public License v3 as published by the Free
8+
Software Foundation.
9+
10+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
11+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
17+
18+
#include <foundation.h>
19+
#include "foundation-private.h"
20+
21+
/* ================================================================
22+
* Default implementations of custom value operations
23+
* ================================================================ */
24+
25+
void
26+
__MCCustomDefaultDestroy (MCValueRef value)
27+
{
28+
}
29+
30+
bool
31+
__MCCustomDefaultCopy (MCValueRef self,
32+
bool p_release,
33+
MCValueRef & r_value)
34+
{
35+
/* This implementation doesn't handle mutable custom values. */
36+
if (MCValueIsMutable (self)) return false;
37+
38+
r_value = MCValueRetain (self);
39+
if (p_release)
40+
MCValueRelease (self);
41+
return true;
42+
}
43+
44+
bool
45+
__MCCustomDefaultEqual (MCValueRef self,
46+
MCValueRef p_other)
47+
{
48+
return (self == p_other);
49+
}
50+
51+
hash_t
52+
__MCCustomDefaultHash (MCValueRef self)
53+
{
54+
return MCHashPointer (self);
55+
}
56+
57+
bool
58+
__MCCustomDefaultDescribe (MCValueRef self,
59+
MCStringRef & r_desc)
60+
{
61+
return false;
62+
}
63+
64+
bool
65+
__MCCustomDefaultIsMutable (MCValueRef self)
66+
{
67+
return false;
68+
}
69+
70+
bool
71+
__MCCustomDefaultMutableCopy (MCValueRef self,
72+
bool release,
73+
MCValueRef & r_value)
74+
{
75+
return false;
76+
}

libfoundation/src/foundation-private.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,15 @@ bool __MCForeignValueCopyDescription(__MCForeignValue *self, MCStringRef& r_desc
536536
bool __MCStreamInitialize(void);
537537
void __MCStreamFinalize(void);
538538

539+
/* Default implementations of each of the function members of struct &
540+
* MCValueCustomCallbacks */
541+
void __MCCustomDefaultDestroy(MCValueRef);
542+
bool __MCCustomDefaultCopy(MCValueRef, bool, MCValueRef &);
543+
bool __MCCustomDefaultEqual(MCValueRef, MCValueRef);
544+
hash_t __MCCustomDefaultHash(MCValueRef);
545+
bool __MCCustomDefaultDescribe(MCValueRef, MCStringRef &);
546+
bool __MCCustomDefaultIsMutable(MCValueRef);
547+
bool __MCCustomDefaultMutableCopy(MCValueRef, bool, MCValueRef &);
539548

540549
////////////////////////////////////////////////////////////////////////////////
541550

libfoundation/src/foundation-value.cpp

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,15 @@ hash_t MCValueHash(MCValueRef p_value)
185185
case kMCValueTypeCodeData:
186186
return __MCDataHash((__MCData*) self);
187187
case kMCValueTypeCodeCustom:
188-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . hash(p_value);
188+
{
189+
MCTypeInfoRef t_typeinfo;
190+
hash_t (*t_hash_func)(MCValueRef);
191+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
192+
t_hash_func = t_typeinfo -> custom . callbacks . hash;
193+
return ((t_hash_func != NULL) ?
194+
t_hash_func (p_value) :
195+
__MCCustomDefaultHash (p_value));
196+
}
189197
case kMCValueTypeCodeProperList:
190198
return __MCProperListHash((__MCProperList *)self);
191199
case kMCValueTypeCodeRecord:
@@ -253,7 +261,15 @@ bool MCValueIsEqualTo(MCValueRef p_value, MCValueRef p_other_value)
253261
// the same.
254262
case kMCValueTypeCodeCustom:
255263
if (((__MCCustomValue *)self) -> typeinfo == ((__MCCustomValue *)other_self) -> typeinfo)
256-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . equal(p_value, p_other_value);
264+
{
265+
MCTypeInfoRef t_typeinfo;
266+
bool (*t_equal_func)(MCValueRef, MCValueRef);
267+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
268+
t_equal_func = t_typeinfo -> custom . callbacks . equal;
269+
return ((t_equal_func != NULL) ?
270+
t_equal_func (p_value, p_other_value) :
271+
__MCCustomDefaultEqual (p_value, p_other_value));
272+
}
257273
return false;
258274
case kMCValueTypeCodeProperList:
259275
return __MCProperListIsEqualTo((__MCProperList*)self, (__MCProperList*)other_self);
@@ -301,7 +317,15 @@ bool MCValueCopyDescription(MCValueRef p_value, MCStringRef& r_desc)
301317
case kMCValueTypeCodeData:
302318
return __MCDataCopyDescription((__MCData*)p_value, r_desc);
303319
case kMCValueTypeCodeCustom:
304-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . describe(p_value, r_desc);
320+
{
321+
MCTypeInfoRef t_typeinfo;
322+
bool (*t_describe_func)(MCValueRef, MCStringRef &);
323+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
324+
t_describe_func = t_typeinfo -> custom . callbacks . describe;
325+
return ((t_describe_func != NULL) ?
326+
t_describe_func (p_value, r_desc) :
327+
__MCCustomDefaultDescribe (p_value, r_desc));
328+
}
305329
case kMCValueTypeCodeProperList:
306330
return __MCProperListCopyDescription((__MCProperList*)p_value, r_desc);
307331
case kMCValueTypeCodeRecord:
@@ -326,8 +350,14 @@ bool MCValueIsMutable(MCValueRef p_value)
326350

327351
if (__MCValueGetTypeCode(self) != kMCValueTypeCodeCustom)
328352
return false;
329-
330-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . is_mutable(p_value);
353+
354+
MCTypeInfoRef t_typeinfo;
355+
bool (*t_is_mutable_func)(MCValueRef);
356+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
357+
t_is_mutable_func = t_typeinfo -> custom . callbacks . is_mutable;
358+
return ((t_is_mutable_func != NULL) ?
359+
t_is_mutable_func (p_value) :
360+
__MCCustomDefaultIsMutable (p_value));
331361
}
332362

333363
bool MCValueMutableCopy(MCValueRef p_value, MCValueRef& r_mutable_copy)
@@ -337,7 +367,13 @@ bool MCValueMutableCopy(MCValueRef p_value, MCValueRef& r_mutable_copy)
337367
if (__MCValueGetTypeCode(self) != kMCValueTypeCodeCustom)
338368
return false;
339369

340-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . mutable_copy(p_value, false, r_mutable_copy);
370+
MCTypeInfoRef t_typeinfo;
371+
bool (*t_mutable_copy_func)(MCValueRef, bool, MCValueRef &);
372+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
373+
t_mutable_copy_func = t_typeinfo -> custom . callbacks . mutable_copy;
374+
return ((t_mutable_copy_func != NULL) ?
375+
t_mutable_copy_func (p_value, false, r_mutable_copy) :
376+
__MCCustomDefaultMutableCopy (p_value, false, r_mutable_copy));
341377
}
342378

343379
bool MCValueMutableCopyAndRelease(MCValueRef p_value, MCValueRef& r_mutable_copy)
@@ -347,7 +383,13 @@ bool MCValueMutableCopyAndRelease(MCValueRef p_value, MCValueRef& r_mutable_copy
347383
if (__MCValueGetTypeCode(self) != kMCValueTypeCodeCustom)
348384
return false;
349385

350-
return __MCCustomValueResolveTypeInfo(self) -> custom . callbacks . mutable_copy(p_value, true, r_mutable_copy);
386+
MCTypeInfoRef t_typeinfo;
387+
bool (*t_mutable_copy_func)(MCValueRef, bool, MCValueRef &);
388+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
389+
t_mutable_copy_func = t_typeinfo -> custom . callbacks . mutable_copy;
390+
return ((t_mutable_copy_func != NULL) ?
391+
t_mutable_copy_func (p_value, true, r_mutable_copy) :
392+
__MCCustomDefaultMutableCopy (p_value, true, r_mutable_copy));
351393
}
352394

353395
////////////////////////////////////////////////////////////////////////////////
@@ -487,7 +529,16 @@ void __MCValueDestroy(__MCValue *self)
487529
__MCProperListDestroy((__MCProperList *)self);
488530
break;
489531
case kMCValueTypeCodeCustom:
490-
__MCCustomValueResolveTypeInfo(self) -> custom . callbacks . destroy(self);
532+
{
533+
MCTypeInfoRef t_typeinfo;
534+
void (*t_destroy_func)(MCValueRef);
535+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
536+
t_destroy_func = t_typeinfo -> custom . callbacks . destroy;
537+
if (t_destroy_func != NULL)
538+
t_destroy_func (self);
539+
else
540+
__MCCustomDefaultDestroy (self);
541+
}
491542
break;
492543
case kMCValueTypeCodeRecord:
493544
__MCRecordDestroy((__MCRecord *)self);
@@ -946,8 +997,14 @@ bool __MCValueImmutableCopy(__MCValue *self, bool p_release, __MCValue*& r_new_v
946997
case kMCValueTypeCodeCustom:
947998
{
948999
MCValueRef t_new_value;
949-
if (__MCCustomValueResolveTypeInfo(self) -> custom . callbacks . copy(self, p_release, t_new_value))
950-
return r_new_value = (__MCValue *)t_new_value, true;
1000+
MCTypeInfoRef t_typeinfo;
1001+
bool (*t_copy_func)(MCValueRef, bool, MCValueRef &);
1002+
t_typeinfo = __MCCustomValueResolveTypeInfo(self);
1003+
t_copy_func = t_typeinfo -> custom . callbacks . copy;
1004+
if ((t_copy_func != NULL) ?
1005+
t_copy_func (self, p_release, t_new_value) :
1006+
__MCCustomDefaultCopy (self, p_release, t_new_value))
1007+
return r_new_value = (__MCValue *) t_new_value, true;
9511008
}
9521009
return false;
9531010

0 commit comments

Comments
 (0)