]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSSerialize.cpp
xnu-344.49.tar.gz
[apple/xnu.git] / libkern / c++ / OSSerialize.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */
26
9bccf70c
A
27#include <sys/cdefs.h>
28
29__BEGIN_DECLS
30#include <vm/vm_kern.h>
31__END_DECLS
32
1c79356b
A
33#include <libkern/c++/OSContainers.h>
34#include <libkern/c++/OSLib.h>
35#include <libkern/c++/OSDictionary.h>
36
37#define super OSObject
38
39OSDefineMetaClassAndStructors(OSSerialize, OSObject)
40OSMetaClassDefineReservedUnused(OSSerialize, 0);
41OSMetaClassDefineReservedUnused(OSSerialize, 1);
42OSMetaClassDefineReservedUnused(OSSerialize, 2);
43OSMetaClassDefineReservedUnused(OSSerialize, 3);
44OSMetaClassDefineReservedUnused(OSSerialize, 4);
45OSMetaClassDefineReservedUnused(OSSerialize, 5);
46OSMetaClassDefineReservedUnused(OSSerialize, 6);
47OSMetaClassDefineReservedUnused(OSSerialize, 7);
48
49#if OSALLOCDEBUG
50extern "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
58char * OSSerialize::text() const
59{
60 return data;
61}
62
63void OSSerialize::clearText()
64{
65 bzero((void *)data, capacity);
66 length = 1;
67 tag = 0;
68 tags->flushCollection();
69}
70
71bool 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
98bool 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
111bool 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
121bool 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
133bool OSSerialize::addString(const char *s)
134{
135 bool rc = false;
136
137 while (*s && (rc = addChar(*s++))) ;
138
139 return rc;
140}
141
142bool 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;
de355530 154 capacity = (inCapacity) ? round_page(inCapacity) : round_page(1);
9bccf70c
A
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) {
1c79356b
A
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
174OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity)
175{
176 OSSerialize *me = new OSSerialize;
177
178 if (me && !me->initWithCapacity(inCapacity)) {
de355530 179 me->free();
1c79356b
A
180 return 0;
181 }
182
183 return me;
184}
185
186unsigned int OSSerialize::getLength() const { return length; }
187unsigned int OSSerialize::getCapacity() const { return capacity; }
188unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; }
189unsigned int OSSerialize::setCapacityIncrement(unsigned int increment)
190{
191 capacityIncrement = (increment)? increment : 256;
192 return capacityIncrement;
193}
194
195unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity)
196{
197 char *newData;
1c79356b
A
198
199 if (newCapacity <= capacity)
200 return capacity;
201
202 // round up
de355530 203 newCapacity = round_page(newCapacity);
9bccf70c
A
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;
1c79356b
A
223 }
224
225 return capacity;
226}
227
228void OSSerialize::free()
229{
230 if (tags)
231 tags->release();
232
233 if (data) {
9bccf70c 234 kmem_free(kernel_map, (vm_offset_t)data, capacity);
1c79356b
A
235 ACCUMSIZE( -capacity );
236 }
237 super::free();
238}
239
240
241OSDefineMetaClassAndStructors(OSSerializer, OSObject)
242
243OSSerializer * OSSerializer::forTarget( void * target,
de355530 244 OSSerializerCallback callback, void * ref = 0 )
1c79356b
A
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
262bool OSSerializer::serialize( OSSerialize * s ) const
263{
264 return( (*callback)(target, ref, s) );
265}