[macruby-changes] [3071] MacRuby/trunk/vm.cpp
source_changes at macosforge.org
source_changes at macosforge.org
Tue Dec 1 18:26:01 PST 2009
Revision: 3071
http://trac.macosforge.org/projects/ruby/changeset/3071
Author: lsansonetti at apple.com
Date: 2009-12-01 18:25:59 -0800 (Tue, 01 Dec 2009)
Log Message:
-----------
<rdar://problem/7319776> Insert into KVO array member fails
Modified Paths:
--------------
MacRuby/trunk/vm.cpp
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2009-12-01 21:36:04 UTC (rev 3070)
+++ MacRuby/trunk/vm.cpp 2009-12-02 02:25:59 UTC (rev 3071)
@@ -1617,6 +1617,49 @@
}
}
+static bool
+kvo_sel(Class klass, const char *selname, const size_t selsize,
+ const char *begin, const char *end)
+{
+ // ^#{begin}(.+)#{end}$ -> token
+ const size_t begin_len = strlen(begin);
+ const size_t end_len = strlen(end);
+ unsigned int token_beg = 0, token_end = 0;
+ if (begin_len > 0) {
+ if (strncmp(selname, begin, begin_len) != 0 || selsize <= begin_len) {
+ return false;
+ }
+ token_beg = begin_len;
+ }
+ if (end_len > 0) {
+ const char *p = strstr(selname, end);
+ if (p == NULL || p + end_len != selname + selsize) {
+ return false;
+ }
+ token_end = p - selname;
+ }
+ const size_t token_len = token_end - token_beg;
+ char token[100];
+ if (token_len > sizeof(token)) {
+ return false;
+ }
+ memcpy(token, &selname[token_beg], token_len);
+ token[token_len] = '\0';
+
+ // token must start with a capital character.
+ if (!isupper(token[0])) {
+ return false;
+ }
+
+ // Decapitalize the token and look if it's a valid KVO attribute.
+ token[0] = tolower(token[0]);
+ if (strchr(token, ':') != NULL) {
+ return false;
+ }
+ SEL sel = sel_registerName(token);
+ return class_getInstanceMethod(klass, sel) != NULL;
+}
+
static inline void
resolve_method_type(char *buf, const size_t buflen, Class klass, Method m,
SEL sel, const unsigned int oc_arity)
@@ -1642,17 +1685,47 @@
}
}
else {
- // Generate an automatic signature, using 'id' (@) for all
- // arguments. If the method name starts by 'set', we use 'void'
- // (v) for the return value, otherwise we use 'id' (@).
- assert(oc_arity < buflen);
- buf[0] = strncmp(sel_getName(sel), "set", 3) == 0 ? 'v' : '@';
- buf[1] = '@';
- buf[2] = ':';
- for (unsigned int i = 3; i < oc_arity; i++) {
- buf[i] = '@';
+ // Generate an automatic signature. We do check for KVO selectors
+ // which require a customized signature, otherwise we do generate
+ // one that assumes that the return value and all arguments are
+ // objects ('@').
+ const char *selname = sel_getName(sel);
+ const size_t selsize = strlen(selname);
+
+ if (kvo_sel(klass, selname, selsize, "countOf", "")) {
+ strncpy(buf, "i@:", buflen);
}
- buf[oc_arity] = '\0';
+ else if (kvo_sel(klass, selname, selsize, "objectIn", "AtIndex:")) {
+ strncpy(buf, "@@:i", buflen);
+ }
+ else if (kvo_sel(klass, selname, selsize, "insertObject:in",
+ "AtIndex:")) {
+ strncpy(buf, "v@:@i", buflen);
+ }
+ else if (kvo_sel(klass, selname, selsize, "removeObjectFrom",
+ "AtIndex:")) {
+ strncpy(buf, "v@:i", buflen);
+ }
+ else if (kvo_sel(klass, selname, selsize, "replaceObjectIn",
+ "AtIndex:withObject:")) {
+ strncpy(buf, "v@:i@", buflen);
+
+ }
+#if 0 // TODO
+ else if (kvo_sel(klass, selname, selsize, "get", ":range:")) {
+ }
+#endif
+ else {
+ assert(oc_arity < buflen);
+
+ buf[0] = strncmp(selname, "set", 3) == 0 ? 'v' : '@';
+ buf[1] = '@';
+ buf[2] = ':';
+ for (unsigned int i = 3; i < oc_arity; i++) {
+ buf[i] = '@';
+ }
+ buf[oc_arity] = '\0';
+ }
}
}
else {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091201/9f3c39fb/attachment.html>
More information about the macruby-changes
mailing list