Port WebCycript parser (CDATA only) to iOS 5.0.
[cydget.git] / yieldToSelector.mm
1 /* Cydia - iPhone UIKit Front-End for Debian APT
2  * Copyright (C) 2008-2011  Jay Freeman (saurik)
3 */
4
5 /* Modified BSD License {{{ */
6 /*
7  *        Redistribution and use in source and binary
8  * forms, with or without modification, are permitted
9  * provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the
12  *    above copyright notice, this list of conditions
13  *    and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the
15  *    above copyright notice, this list of conditions
16  *    and the following disclaimer in the documentation
17  *    and/or other materials provided with the
18  *    distribution.
19  * 3. The name of the author may not be used to endorse
20  *    or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* }}} */
39
40 #include "yieldToSelector.h"
41
42 @implementation NSObject (CydgetYieldToSelector)
43
44 - (void) cydget$doNothing {
45 }
46
47 - (void) cydget$yieldToContext:(NSMutableArray *)context {
48     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
49
50     SEL selector(reinterpret_cast<SEL>([[context objectAtIndex:0] pointerValue]));
51     id object([[context objectAtIndex:1] nonretainedObjectValue]);
52     volatile bool &stopped(*reinterpret_cast<bool *>([[context objectAtIndex:2] pointerValue]));
53
54     /* XXX: deal with exceptions */
55     id value([self performSelector:selector withObject:object]);
56
57     NSMethodSignature *signature([self methodSignatureForSelector:selector]);
58     [context removeAllObjects];
59     if ([signature methodReturnLength] != 0 && value != nil)
60         [context addObject:value];
61
62     stopped = true;
63
64     [self
65         performSelectorOnMainThread:@selector(cydget$doNothing)
66         withObject:nil
67         waitUntilDone:NO
68     ];
69
70     [pool release];
71 }
72
73 - (id) cydget$yieldToSelector:(SEL)selector withObject:(id)object {
74     volatile bool stopped(false);
75
76     NSMutableArray *context([NSMutableArray arrayWithObjects:
77         [NSValue valueWithPointer:selector],
78         [NSValue valueWithNonretainedObject:object],
79         [NSValue valueWithPointer:const_cast<bool *>(&stopped)],
80     nil]);
81
82     NSThread *thread([[[NSThread alloc]
83         initWithTarget:self
84         selector:@selector(cydget$yieldToContext:)
85         object:context
86     ] autorelease]);
87
88     [thread start];
89
90     NSRunLoop *loop([NSRunLoop currentRunLoop]);
91     NSDate *future([NSDate distantFuture]);
92     NSString *mode([loop currentMode] ?: NSDefaultRunLoopMode);
93
94     while (!stopped && [loop runMode:mode beforeDate:future]);
95
96     return [context count] == 0 ? nil : [context objectAtIndex:0];
97 }
98
99 - (id) cydget$yieldToSelector:(SEL)selector {
100     return [self cydget$yieldToSelector:selector withObject:nil];
101 }
102
103 @end
104