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