]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
2d21ac55 | 2 | * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */ | |
29 | ||
9bccf70c A |
30 | #include <sys/cdefs.h> |
31 | ||
32 | __BEGIN_DECLS | |
33 | #include <vm/vm_kern.h> | |
34 | __END_DECLS | |
35 | ||
1c79356b A |
36 | #include <libkern/c++/OSContainers.h> |
37 | #include <libkern/c++/OSLib.h> | |
38 | #include <libkern/c++/OSDictionary.h> | |
fe8ab488 | 39 | #include <libkern/OSSerializeBinary.h> |
d9a64523 | 40 | #include <libkern/Block.h> |
3e170ce0 | 41 | #include <IOKit/IOLib.h> |
1c79356b A |
42 | |
43 | #define super OSObject | |
44 | ||
45 | OSDefineMetaClassAndStructors(OSSerialize, OSObject) | |
46 | OSMetaClassDefineReservedUnused(OSSerialize, 0); | |
47 | OSMetaClassDefineReservedUnused(OSSerialize, 1); | |
48 | OSMetaClassDefineReservedUnused(OSSerialize, 2); | |
49 | OSMetaClassDefineReservedUnused(OSSerialize, 3); | |
50 | OSMetaClassDefineReservedUnused(OSSerialize, 4); | |
51 | OSMetaClassDefineReservedUnused(OSSerialize, 5); | |
52 | OSMetaClassDefineReservedUnused(OSSerialize, 6); | |
53 | OSMetaClassDefineReservedUnused(OSSerialize, 7); | |
54 | ||
1c79356b A |
55 | |
56 | char * OSSerialize::text() const | |
57 | { | |
58 | return data; | |
59 | } | |
60 | ||
61 | void OSSerialize::clearText() | |
62 | { | |
fe8ab488 A |
63 | if (binary) |
64 | { | |
65 | length = sizeof(kOSSerializeBinarySignature); | |
66 | bzero(&data[length], capacity - length); | |
67 | endCollection = true; | |
68 | } | |
69 | else | |
70 | { | |
71 | bzero((void *)data, capacity); | |
72 | length = 1; | |
73 | } | |
1c79356b A |
74 | tags->flushCollection(); |
75 | } | |
76 | ||
77 | bool OSSerialize::previouslySerialized(const OSMetaClassBase *o) | |
78 | { | |
79 | char temp[16]; | |
39037602 | 80 | unsigned int tagIdx; |
1c79356b | 81 | |
fe8ab488 A |
82 | if (binary) return (binarySerialize(o)); |
83 | ||
1c79356b | 84 | // look it up |
39037602 | 85 | tagIdx = tags->getNextIndexOfObject(o, 0); |
1c79356b | 86 | |
b0d623f7 | 87 | // xx-review: no error checking here for addString calls! |
1c79356b | 88 | // does it exist? |
39037602 | 89 | if (tagIdx != -1U) { |
1c79356b | 90 | addString("<reference IDREF=\""); |
39037602 A |
91 | snprintf(temp, sizeof(temp), "%u", tagIdx); |
92 | addString(temp); | |
1c79356b A |
93 | addString("\"/>"); |
94 | return true; | |
95 | } | |
96 | ||
39037602 A |
97 | // add to tag array |
98 | tags->setObject(o);// XXX check return | |
1c79356b A |
99 | |
100 | return false; | |
101 | } | |
102 | ||
103 | bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString) | |
104 | { | |
39037602 A |
105 | char temp[16]; |
106 | unsigned int tagIdx; | |
107 | ||
fe8ab488 A |
108 | if (binary) |
109 | { | |
110 | printf("class %s: xml serialize\n", o->getMetaClass()->getClassName()); | |
111 | return (false); | |
112 | } | |
1c79356b A |
113 | |
114 | if (!addChar('<')) return false; | |
115 | if (!addString(tagString)) return false; | |
116 | if (!addString(" ID=\"")) return false; | |
39037602 A |
117 | tagIdx = tags->getNextIndexOfObject(o, 0); |
118 | assert(tagIdx != -1U); | |
119 | snprintf(temp, sizeof(temp), "%u", tagIdx); | |
120 | if (!addString(temp)) | |
1c79356b A |
121 | return false; |
122 | if (!addChar('\"')) return false; | |
123 | if (!addChar('>')) return false; | |
124 | return true; | |
125 | } | |
126 | ||
127 | bool OSSerialize::addXMLEndTag(const char *tagString) | |
128 | { | |
129 | ||
130 | if (!addChar('<')) return false; | |
131 | if (!addChar('/')) return false; | |
132 | if (!addString(tagString)) return false; | |
133 | if (!addChar('>')) return false; | |
134 | return true; | |
135 | } | |
136 | ||
137 | bool OSSerialize::addChar(const char c) | |
138 | { | |
fe8ab488 A |
139 | if (binary) |
140 | { | |
141 | printf("xml serialize\n"); | |
142 | return (false); | |
143 | } | |
144 | ||
1c79356b A |
145 | // add char, possibly extending our capacity |
146 | if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement)) | |
147 | return false; | |
148 | ||
149 | data[length - 1] = c; | |
150 | length++; | |
151 | ||
152 | return true; | |
153 | } | |
154 | ||
155 | bool OSSerialize::addString(const char *s) | |
156 | { | |
157 | bool rc = false; | |
158 | ||
159 | while (*s && (rc = addChar(*s++))) ; | |
160 | ||
161 | return rc; | |
162 | } | |
163 | ||
164 | bool OSSerialize::initWithCapacity(unsigned int inCapacity) | |
165 | { | |
166 | if (!super::init()) | |
167 | return false; | |
168 | ||
39037602 | 169 | tags = OSArray::withCapacity(256); |
1c79356b A |
170 | if (!tags) { |
171 | return false; | |
172 | } | |
173 | ||
1c79356b | 174 | length = 1; |
39037602 A |
175 | |
176 | if (!inCapacity) { | |
177 | inCapacity = 1; | |
178 | } | |
179 | if (round_page_overflow(inCapacity, &capacity)) { | |
180 | tags->release(); | |
181 | tags = 0; | |
182 | return false; | |
183 | } | |
184 | ||
9bccf70c A |
185 | capacityIncrement = capacity; |
186 | ||
187 | // allocate from the kernel map so that we can safely map this data | |
188 | // into user space (the primary use of the OSSerialize object) | |
189 | ||
3e170ce0 | 190 | kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity, IOMemoryTag(kernel_map)); |
9bccf70c | 191 | if (rc) { |
1c79356b A |
192 | tags->release(); |
193 | tags = 0; | |
194 | return false; | |
195 | } | |
196 | bzero((void *)data, capacity); | |
197 | ||
198 | ||
3e170ce0 | 199 | OSCONTAINER_ACCUMSIZE(capacity); |
1c79356b A |
200 | |
201 | return true; | |
202 | } | |
203 | ||
204 | OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity) | |
205 | { | |
206 | OSSerialize *me = new OSSerialize; | |
207 | ||
208 | if (me && !me->initWithCapacity(inCapacity)) { | |
55e303ae | 209 | me->release(); |
1c79356b A |
210 | return 0; |
211 | } | |
212 | ||
213 | return me; | |
214 | } | |
215 | ||
216 | unsigned int OSSerialize::getLength() const { return length; } | |
217 | unsigned int OSSerialize::getCapacity() const { return capacity; } | |
218 | unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; } | |
219 | unsigned int OSSerialize::setCapacityIncrement(unsigned int increment) | |
220 | { | |
221 | capacityIncrement = (increment)? increment : 256; | |
222 | return capacityIncrement; | |
223 | } | |
224 | ||
225 | unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity) | |
226 | { | |
227 | char *newData; | |
1c79356b A |
228 | |
229 | if (newCapacity <= capacity) | |
230 | return capacity; | |
231 | ||
39037602 A |
232 | if (round_page_overflow(newCapacity, &newCapacity)) { |
233 | return capacity; | |
234 | } | |
9bccf70c A |
235 | |
236 | kern_return_t rc = kmem_realloc(kernel_map, | |
237 | (vm_offset_t)data, | |
238 | capacity, | |
239 | (vm_offset_t *)&newData, | |
3e170ce0 A |
240 | newCapacity, |
241 | VM_KERN_MEMORY_IOKIT); | |
9bccf70c | 242 | if (!rc) { |
3e170ce0 | 243 | OSCONTAINER_ACCUMSIZE(newCapacity); |
9bccf70c A |
244 | |
245 | // kmem realloc does not free the old address range | |
246 | kmem_free(kernel_map, (vm_offset_t)data, capacity); | |
3e170ce0 | 247 | OSCONTAINER_ACCUMSIZE(-((size_t)capacity)); |
9bccf70c A |
248 | |
249 | // kmem realloc does not zero out the new memory | |
250 | // and this could end up going to user land | |
251 | bzero(&newData[capacity], newCapacity - capacity); | |
252 | ||
253 | data = newData; | |
254 | capacity = newCapacity; | |
1c79356b A |
255 | } |
256 | ||
257 | return capacity; | |
258 | } | |
259 | ||
260 | void OSSerialize::free() | |
261 | { | |
262 | if (tags) | |
263 | tags->release(); | |
264 | ||
265 | if (data) { | |
9bccf70c | 266 | kmem_free(kernel_map, (vm_offset_t)data, capacity); |
3e170ce0 | 267 | OSCONTAINER_ACCUMSIZE( -((size_t)capacity) ); |
1c79356b A |
268 | } |
269 | super::free(); | |
270 | } | |
271 | ||
272 | ||
273 | OSDefineMetaClassAndStructors(OSSerializer, OSObject) | |
274 | ||
275 | OSSerializer * OSSerializer::forTarget( void * target, | |
55e303ae | 276 | OSSerializerCallback callback, void * ref ) |
1c79356b A |
277 | { |
278 | OSSerializer * thing; | |
279 | ||
280 | thing = new OSSerializer; | |
281 | if( thing && !thing->init()) { | |
282 | thing->release(); | |
283 | thing = 0; | |
284 | } | |
285 | ||
286 | if( thing) { | |
287 | thing->target = target; | |
288 | thing->ref = ref; | |
289 | thing->callback = callback; | |
290 | } | |
291 | return( thing ); | |
292 | } | |
293 | ||
d9a64523 A |
294 | bool OSSerializer::callbackToBlock(void * target __unused, void * ref, |
295 | OSSerialize * serializer) | |
296 | { | |
297 | return ((OSSerializerBlock)ref)(serializer); | |
298 | } | |
299 | ||
300 | OSSerializer * OSSerializer::withBlock( | |
301 | OSSerializerBlock callback) | |
302 | { | |
303 | OSSerializer * serializer; | |
304 | OSSerializerBlock block; | |
305 | ||
306 | block = Block_copy(callback); | |
307 | if (!block) return (0); | |
308 | ||
309 | serializer = (OSSerializer::forTarget(NULL, &OSSerializer::callbackToBlock, block)); | |
310 | ||
311 | if (!serializer) Block_release(block); | |
312 | ||
313 | return (serializer); | |
314 | } | |
315 | ||
316 | void OSSerializer::free(void) | |
317 | { | |
318 | if (callback == &callbackToBlock) Block_release(ref); | |
319 | ||
320 | super::free(); | |
321 | } | |
322 | ||
1c79356b A |
323 | bool OSSerializer::serialize( OSSerialize * s ) const |
324 | { | |
325 | return( (*callback)(target, ref, s) ); | |
326 | } |