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