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