]> git.saurik.com Git - apple/libdispatch.git/blob - src/data.m
libdispatch-703.1.4.tar.gz
[apple/libdispatch.git] / src / data.m
1 /*
2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21 #include "internal.h"
22
23 #if DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
24
25 #if _OS_OBJECT_OBJC_ARC
26 #error "Cannot build with ARC"
27 #endif
28
29 #include <Foundation/NSString.h>
30
31 @interface DISPATCH_CLASS(data) () <DISPATCH_CLASS(data)>
32 @property (readonly) NSUInteger length;
33 @property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
34
35 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
36 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm;
37 - (BOOL)_bytesAreVM;
38 - (BOOL)_isCompact;
39 @end
40
41 @interface DISPATCH_CLASS(data_empty) : DISPATCH_CLASS(data)
42 @end
43
44 @implementation DISPATCH_CLASS(data)
45
46 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
47 return _dispatch_objc_alloc(self, sizeof(struct dispatch_data_s));
48 }
49
50 - (id)init {
51 return [self initWithBytes:NULL length:0 copy:NO freeWhenDone:NO
52 bytesAreVM:NO];
53 }
54
55 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
56 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm {
57 dispatch_block_t destructor;
58 if (copy) {
59 destructor = DISPATCH_DATA_DESTRUCTOR_DEFAULT;
60 } else if (freeBytes) {
61 if (vm) {
62 destructor = DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
63 } else {
64 destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
65 }
66 } else {
67 destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
68 }
69 dispatch_data_init(self, bytes, length, destructor);
70 return self;
71 }
72
73 #define _dispatch_data_objc_dispose(selector) \
74 struct dispatch_data_s *dd = (void*)self; \
75 _dispatch_data_dispose(self); \
76 dispatch_queue_t tq = dd->do_targetq; \
77 dispatch_function_t func = dd->finalizer; \
78 void *ctxt = dd->ctxt; \
79 [super selector]; \
80 if (func && ctxt) { \
81 if (!tq) { \
82 tq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);\
83 } \
84 dispatch_async_f(tq, ctxt, func); \
85 } \
86 if (tq) { \
87 _os_object_release_internal((_os_object_t)tq); \
88 }
89
90 - (void)dealloc {
91 _dispatch_data_objc_dispose(dealloc);
92 }
93
94 - (BOOL)_bytesAreVM {
95 struct dispatch_data_s *dd = (void*)self;
96 return dd->destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
97 }
98
99 - (void)_setContext:(void*)context {
100 struct dispatch_data_s *dd = (void*)self;
101 dd->ctxt = context;
102 }
103
104 - (void*)_getContext {
105 struct dispatch_data_s *dd = (void*)self;
106 return dd->ctxt;
107 }
108
109 - (void)_setFinalizer:(dispatch_function_t)finalizer {
110 struct dispatch_data_s *dd = (void*)self;
111 dd->finalizer = finalizer;
112 }
113
114 - (void)_setTargetQueue:(dispatch_queue_t)queue {
115 struct dispatch_data_s *dd = (void*)self;
116 _os_object_retain_internal((_os_object_t)queue);
117 dispatch_queue_t prev;
118 prev = os_atomic_xchg2o(dd, do_targetq, queue, release);
119 if (prev) _os_object_release_internal((_os_object_t)prev);
120 }
121
122 - (NSString *)debugDescription {
123 Class nsstring = objc_lookUpClass("NSString");
124 if (!nsstring) return nil;
125 char buf[2048];
126 _dispatch_data_debug(self, buf, sizeof(buf));
127 return [nsstring stringWithFormat:
128 [nsstring stringWithUTF8String:"<%s: %s>"],
129 class_getName([self class]), buf];
130 }
131
132 - (NSUInteger)length {
133 struct dispatch_data_s *dd = (void*)self;
134 return dd->size;
135 }
136
137 - (const void *)bytes {
138 struct dispatch_data_s *dd = (void*)self;
139 return _dispatch_data_get_flattened_bytes(dd);
140 }
141
142 - (BOOL)_isCompact {
143 struct dispatch_data_s *dd = (void*)self;
144 return !dd->size || _dispatch_data_map_direct(dd, 0, NULL, NULL) != NULL;
145 }
146
147 - (void)_suspend {
148 }
149
150 - (void)_resume {
151 }
152
153 - (void)_activate {
154 }
155
156 @end
157
158 @implementation DISPATCH_CLASS(data_empty)
159
160 // Force non-lazy class realization rdar://10640168
161 + (void)load {
162 }
163
164 - (id)retain {
165 return (id)self;
166 }
167
168 - (oneway void)release {
169 }
170
171 - (id)autorelease {
172 return (id)self;
173 }
174
175 - (NSUInteger)retainCount {
176 return ULONG_MAX;
177 }
178
179 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
180 return (id)&_dispatch_data_empty;
181 }
182
183 - (void)_setContext:(void*) DISPATCH_UNUSED context {
184 }
185
186 - (void*)_getContext {
187 return NULL;
188 }
189
190 - (void)_setFinalizer:(dispatch_function_t) DISPATCH_UNUSED finalizer {
191 }
192
193 - (void)_setTargetQueue:(dispatch_queue_t) DISPATCH_UNUSED queue {
194 }
195
196 - (void)_suspend {
197 }
198
199 - (void)_resume {
200 }
201
202 - (void)_activate {
203 }
204
205 @end
206
207 #endif // USE_OBJC