]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSSerialize.cpp
xnu-344.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 *
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
9bccf70c
A
24#include <sys/cdefs.h>
25
26__BEGIN_DECLS
27#include <vm/vm_kern.h>
28__END_DECLS
29
1c79356b
A
30#include <libkern/c++/OSContainers.h>
31#include <libkern/c++/OSLib.h>
32#include <libkern/c++/OSDictionary.h>
33
34#define super OSObject
35
36OSDefineMetaClassAndStructors(OSSerialize, OSObject)
37OSMetaClassDefineReservedUnused(OSSerialize, 0);
38OSMetaClassDefineReservedUnused(OSSerialize, 1);
39OSMetaClassDefineReservedUnused(OSSerialize, 2);
40OSMetaClassDefineReservedUnused(OSSerialize, 3);
41OSMetaClassDefineReservedUnused(OSSerialize, 4);
42OSMetaClassDefineReservedUnused(OSSerialize, 5);
43OSMetaClassDefineReservedUnused(OSSerialize, 6);
44OSMetaClassDefineReservedUnused(OSSerialize, 7);
45
46#if OSALLOCDEBUG
47extern "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
55char * OSSerialize::text() const
56{
57 return data;
58}
59
60void OSSerialize::clearText()
61{
62 bzero((void *)data, capacity);
63 length = 1;
64 tag = 0;
65 tags->flushCollection();
66}
67
68bool 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
95bool 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
108bool 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
118bool 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
130bool OSSerialize::addString(const char *s)
131{
132 bool rc = false;
133
134 while (*s && (rc = addChar(*s++))) ;
135
136 return rc;
137}
138
139bool 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;
9bccf70c
A
151 capacity = (inCapacity) ? round_page(inCapacity) : round_page(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) {
1c79356b
A
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
171OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity)
172{
173 OSSerialize *me = new OSSerialize;
174
175 if (me && !me->initWithCapacity(inCapacity)) {
176 me->free();
177 return 0;
178 }
179
180 return me;
181}
182
183unsigned int OSSerialize::getLength() const { return length; }
184unsigned int OSSerialize::getCapacity() const { return capacity; }
185unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; }
186unsigned int OSSerialize::setCapacityIncrement(unsigned int increment)
187{
188 capacityIncrement = (increment)? increment : 256;
189 return capacityIncrement;
190}
191
192unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity)
193{
194 char *newData;
1c79356b
A
195
196 if (newCapacity <= capacity)
197 return capacity;
198
199 // round up
9bccf70c
A
200 newCapacity = round_page(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;
1c79356b
A
220 }
221
222 return capacity;
223}
224
225void OSSerialize::free()
226{
227 if (tags)
228 tags->release();
229
230 if (data) {
9bccf70c 231 kmem_free(kernel_map, (vm_offset_t)data, capacity);
1c79356b
A
232 ACCUMSIZE( -capacity );
233 }
234 super::free();
235}
236
237
238OSDefineMetaClassAndStructors(OSSerializer, OSObject)
239
240OSSerializer * OSSerializer::forTarget( void * target,
241 OSSerializerCallback callback, void * ref = 0 )
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
259bool OSSerializer::serialize( OSSerialize * s ) const
260{
261 return( (*callback)(target, ref, s) );
262}