]> git.saurik.com Git - apple/libdispatch.git/blob - src/data.m
libdispatch-501.20.1.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 USE_OBJC
24
25 #if !__OBJC2__
26 #error "Cannot build with legacy ObjC runtime"
27 #endif
28 #if _OS_OBJECT_OBJC_ARC
29 #error "Cannot build with ARC"
30 #endif
31
32 #include <Foundation/NSString.h>
33
34 @interface DISPATCH_CLASS(data) ()
35 @property (readonly) NSUInteger length;
36 @property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
37
38 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
39 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm;
40 - (BOOL)_bytesAreVM;
41 - (BOOL)_isCompact;
42 @end
43
44 @interface DISPATCH_CLASS(data_empty) : DISPATCH_CLASS(data)
45 @end
46
47 @implementation DISPATCH_CLASS(data)
48
49 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
50 return _dispatch_objc_alloc(self, sizeof(struct dispatch_data_s));
51 }
52
53 - (id)init {
54 return [self initWithBytes:NULL length:0 copy:NO freeWhenDone:NO
55 bytesAreVM:NO];
56 }
57
58 - (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
59 freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm {
60 dispatch_block_t destructor;
61 if (copy) {
62 destructor = DISPATCH_DATA_DESTRUCTOR_DEFAULT;
63 } else if (freeBytes) {
64 if (vm) {
65 destructor = DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
66 } else {
67 destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
68 }
69 } else {
70 destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
71 }
72 dispatch_data_init(self, bytes, length, destructor);
73 return self;
74 }
75
76 #define _dispatch_data_objc_dispose(selector) \
77 struct dispatch_data_s *dd = (void*)self; \
78 _dispatch_data_dispose(self); \
79 dispatch_queue_t tq = dd->do_targetq; \
80 dispatch_function_t func = dd->finalizer; \
81 void *ctxt = dd->ctxt; \
82 [super selector]; \
83 if (func && ctxt) { \
84 if (!tq) { \
85 tq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);\
86 } \
87 dispatch_async_f(tq, ctxt, func); \
88 } \
89 if (tq) { \
90 _os_object_release_internal((_os_object_t)tq); \
91 }
92
93 - (void)dealloc {
94 _dispatch_data_objc_dispose(dealloc);
95 }
96
97 - (void)finalize {
98 _dispatch_data_objc_dispose(finalize);
99 }
100
101 - (BOOL)_bytesAreVM {
102 struct dispatch_data_s *dd = (void*)self;
103 return dd->destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
104 }
105
106 - (void)_setContext:(void*)context {
107 struct dispatch_data_s *dd = (void*)self;
108 dd->ctxt = context;
109 }
110
111 - (void*)_getContext {
112 struct dispatch_data_s *dd = (void*)self;
113 return dd->ctxt;
114 }
115
116 - (void)_setFinalizer:(dispatch_function_t)finalizer {
117 struct dispatch_data_s *dd = (void*)self;
118 dd->finalizer = finalizer;
119 }
120
121 - (void)_setTargetQueue:(dispatch_queue_t)queue {
122 struct dispatch_data_s *dd = (void*)self;
123 _os_object_retain_internal((_os_object_t)queue);
124 dispatch_queue_t prev;
125 prev = dispatch_atomic_xchg2o(dd, do_targetq, queue, release);
126 if (prev) _os_object_release_internal((_os_object_t)prev);
127 }
128
129 - (NSString *)debugDescription {
130 Class nsstring = objc_lookUpClass("NSString");
131 if (!nsstring) return nil;
132 char buf[2048];
133 _dispatch_data_debug(self, buf, sizeof(buf));
134 return [nsstring stringWithFormat:
135 [nsstring stringWithUTF8String:"<%s: %s>"],
136 class_getName([self class]), buf];
137 }
138
139 - (NSUInteger)length {
140 struct dispatch_data_s *dd = (void*)self;
141 return dd->size;
142 }
143
144 - (const void *)bytes {
145 struct dispatch_data_s *dd = (void*)self;
146 return _dispatch_data_get_flattened_bytes(dd);
147 }
148
149 - (BOOL)_isCompact {
150 struct dispatch_data_s *dd = (void*)self;
151 return !dd->size || _dispatch_data_map_direct(dd, 0, NULL, NULL) != NULL;
152 }
153
154 @end
155
156 @implementation DISPATCH_CLASS(data_empty)
157
158 // Force non-lazy class realization rdar://10640168
159 + (void)load {
160 }
161
162 - (id)retain {
163 return (id)self;
164 }
165
166 - (oneway void)release {
167 }
168
169 - (id)autorelease {
170 return (id)self;
171 }
172
173 - (NSUInteger)retainCount {
174 return ULONG_MAX;
175 }
176
177 + (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
178 return (id)&_dispatch_data_empty;
179 }
180
181 - (void)_setContext:(void*) DISPATCH_UNUSED context {
182 }
183
184 - (void*)_getContext {
185 return NULL;
186 }
187
188 - (void)_setFinalizer:(dispatch_function_t) DISPATCH_UNUSED finalizer {
189 }
190
191 - (void)_setTargetQueue:(dispatch_queue_t) DISPATCH_UNUSED queue {
192 }
193
194 @end
195
196 #endif // USE_OBJC