]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSSerialize.cpp
d71d2c7cdc58e5d8382e2a3e58e657a361b98c54
[apple/xnu.git] / libkern / c++ / OSSerialize.cpp
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */
26
27 #include <sys/cdefs.h>
28
29 __BEGIN_DECLS
30 #include <vm/vm_kern.h>
31 __END_DECLS
32
33 #include <libkern/c++/OSContainers.h>
34 #include <libkern/c++/OSLib.h>
35 #include <libkern/c++/OSDictionary.h>
36
37 #define super OSObject
38
39 OSDefineMetaClassAndStructors(OSSerialize, OSObject)
40 OSMetaClassDefineReservedUnused(OSSerialize, 0);
41 OSMetaClassDefineReservedUnused(OSSerialize, 1);
42 OSMetaClassDefineReservedUnused(OSSerialize, 2);
43 OSMetaClassDefineReservedUnused(OSSerialize, 3);
44 OSMetaClassDefineReservedUnused(OSSerialize, 4);
45 OSMetaClassDefineReservedUnused(OSSerialize, 5);
46 OSMetaClassDefineReservedUnused(OSSerialize, 6);
47 OSMetaClassDefineReservedUnused(OSSerialize, 7);
48
49 #if OSALLOCDEBUG
50 extern "C" {
51 extern int debug_container_malloc_size;
52 };
53 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
54 #else
55 #define ACCUMSIZE(s)
56 #endif
57
58 char * OSSerialize::text() const
59 {
60 return data;
61 }
62
63 void OSSerialize::clearText()
64 {
65 bzero((void *)data, capacity);
66 length = 1;
67 tag = 0;
68 tags->flushCollection();
69 }
70
71 bool OSSerialize::previouslySerialized(const OSMetaClassBase *o)
72 {
73 char temp[16];
74 OSString *tagString;
75
76 // look it up
77 tagString = (OSString *)tags->getObject((const OSSymbol *) o);
78
79 // does it exist?
80 if (tagString) {
81 addString("<reference IDREF=\"");
82 addString(tagString->getCStringNoCopy());
83 addString("\"/>");
84 return true;
85 }
86
87 // build a tag
88 sprintf(temp, "%u", tag++);
89 tagString = OSString::withCString(temp);
90
91 // add to tag dictionary
92 tags->setObject((const OSSymbol *) o, tagString);// XXX check return
93 tagString->release();
94
95 return false;
96 }
97
98 bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString)
99 {
100
101 if (!addChar('<')) return false;
102 if (!addString(tagString)) return false;
103 if (!addString(" ID=\"")) return false;
104 if (!addString(((OSString *)tags->getObject((const OSSymbol *)o))->getCStringNoCopy()))
105 return false;
106 if (!addChar('\"')) return false;
107 if (!addChar('>')) return false;
108 return true;
109 }
110
111 bool OSSerialize::addXMLEndTag(const char *tagString)
112 {
113
114 if (!addChar('<')) return false;
115 if (!addChar('/')) return false;
116 if (!addString(tagString)) return false;
117 if (!addChar('>')) return false;
118 return true;
119 }
120
121 bool OSSerialize::addChar(const char c)
122 {
123 // add char, possibly extending our capacity
124 if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement))
125 return false;
126
127 data[length - 1] = c;
128 length++;
129
130 return true;
131 }
132
133 bool OSSerialize::addString(const char *s)
134 {
135 bool rc = false;
136
137 while (*s && (rc = addChar(*s++))) ;
138
139 return rc;
140 }
141
142 bool OSSerialize::initWithCapacity(unsigned int inCapacity)
143 {
144 if (!super::init())
145 return false;
146
147 tags = OSDictionary::withCapacity(32);
148 if (!tags) {
149 return false;
150 }
151
152 tag = 0;
153 length = 1;
154 capacity = (inCapacity) ? round_page(inCapacity) : round_page(1);
155 capacityIncrement = capacity;
156
157 // allocate from the kernel map so that we can safely map this data
158 // into user space (the primary use of the OSSerialize object)
159
160 kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity);
161 if (rc) {
162 tags->release();
163 tags = 0;
164 return false;
165 }
166 bzero((void *)data, capacity);
167
168
169 ACCUMSIZE(capacity);
170
171 return true;
172 }
173
174 OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity)
175 {
176 OSSerialize *me = new OSSerialize;
177
178 if (me && !me->initWithCapacity(inCapacity)) {
179 me->free();
180 return 0;
181 }
182
183 return me;
184 }
185
186 unsigned int OSSerialize::getLength() const { return length; }
187 unsigned int OSSerialize::getCapacity() const { return capacity; }
188 unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; }
189 unsigned int OSSerialize::setCapacityIncrement(unsigned int increment)
190 {
191 capacityIncrement = (increment)? increment : 256;
192 return capacityIncrement;
193 }
194
195 unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity)
196 {
197 char *newData;
198
199 if (newCapacity <= capacity)
200 return capacity;
201
202 // round up
203 newCapacity = round_page(newCapacity);
204
205 kern_return_t rc = kmem_realloc(kernel_map,
206 (vm_offset_t)data,
207 capacity,
208 (vm_offset_t *)&newData,
209 newCapacity);
210 if (!rc) {
211 ACCUMSIZE(newCapacity);
212
213 // kmem realloc does not free the old address range
214 kmem_free(kernel_map, (vm_offset_t)data, capacity);
215 ACCUMSIZE(-capacity);
216
217 // kmem realloc does not zero out the new memory
218 // and this could end up going to user land
219 bzero(&newData[capacity], newCapacity - capacity);
220
221 data = newData;
222 capacity = newCapacity;
223 }
224
225 return capacity;
226 }
227
228 void OSSerialize::free()
229 {
230 if (tags)
231 tags->release();
232
233 if (data) {
234 kmem_free(kernel_map, (vm_offset_t)data, capacity);
235 ACCUMSIZE( -capacity );
236 }
237 super::free();
238 }
239
240
241 OSDefineMetaClassAndStructors(OSSerializer, OSObject)
242
243 OSSerializer * OSSerializer::forTarget( void * target,
244 OSSerializerCallback callback, void * ref = 0 )
245 {
246 OSSerializer * thing;
247
248 thing = new OSSerializer;
249 if( thing && !thing->init()) {
250 thing->release();
251 thing = 0;
252 }
253
254 if( thing) {
255 thing->target = target;
256 thing->ref = ref;
257 thing->callback = callback;
258 }
259 return( thing );
260 }
261
262 bool OSSerializer::serialize( OSSerialize * s ) const
263 {
264 return( (*callback)(target, ref, s) );
265 }