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