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> 39c1dac77fSApple OSS Distributions 40c1dac77fSApple OSS Distributions #define super OSObject 41c1dac77fSApple OSS Distributions 42c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(OSSerialize, OSObject) 43c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 0); 44c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 1); 45c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 2); 46c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 3); 47c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 4); 48c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 5); 49c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 6); 50c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(OSSerialize, 7); 51c1dac77fSApple OSS Distributions 52c1dac77fSApple OSS Distributions #if OSALLOCDEBUG 53c1dac77fSApple OSS Distributions extern "C" { 54c1dac77fSApple OSS Distributions extern int debug_container_malloc_size; 55c1dac77fSApple OSS Distributions }; 56c1dac77fSApple OSS Distributions #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 57c1dac77fSApple OSS Distributions #else 58c1dac77fSApple OSS Distributions #define ACCUMSIZE(s) 59c1dac77fSApple OSS Distributions #endif 60c1dac77fSApple OSS Distributions 61c1dac77fSApple OSS Distributions char * OSSerialize::text() const 62c1dac77fSApple OSS Distributions { 63c1dac77fSApple OSS Distributions return data; 64c1dac77fSApple OSS Distributions } 65c1dac77fSApple OSS Distributions 66c1dac77fSApple OSS Distributions void OSSerialize::clearText() 67c1dac77fSApple OSS Distributions { 68c1dac77fSApple OSS Distributions bzero((void *)data, capacity); 69c1dac77fSApple OSS Distributions length = 1; 70c1dac77fSApple OSS Distributions tag = 0; 71c1dac77fSApple OSS Distributions tags->flushCollection(); 72c1dac77fSApple OSS Distributions } 73c1dac77fSApple OSS Distributions 74c1dac77fSApple OSS Distributions bool OSSerialize::previouslySerialized(const OSMetaClassBase *o) 75c1dac77fSApple OSS Distributions { 76c1dac77fSApple OSS Distributions char temp[16]; 77c1dac77fSApple OSS Distributions OSString *tagString; 78c1dac77fSApple OSS Distributions 79c1dac77fSApple OSS Distributions // look it up 80c1dac77fSApple OSS Distributions tagString = (OSString *)tags->getObject((const OSSymbol *) o); 81c1dac77fSApple OSS Distributions 82*3ca3bd55SApple OSS Distributions // xx-review: no error checking here for addString calls! 83c1dac77fSApple OSS Distributions // does it exist? 84c1dac77fSApple OSS Distributions if (tagString) { 85c1dac77fSApple OSS Distributions addString("<reference IDREF=\""); 86c1dac77fSApple OSS Distributions addString(tagString->getCStringNoCopy()); 87c1dac77fSApple OSS Distributions addString("\"/>"); 88c1dac77fSApple OSS Distributions return true; 89c1dac77fSApple OSS Distributions } 90c1dac77fSApple OSS Distributions 91c1dac77fSApple OSS Distributions // build a tag 92e13b1fa5SApple OSS Distributions snprintf(temp, sizeof(temp), "%u", tag++); 93c1dac77fSApple OSS Distributions tagString = OSString::withCString(temp); 94c1dac77fSApple OSS Distributions 95c1dac77fSApple OSS Distributions // add to tag dictionary 96c1dac77fSApple OSS Distributions tags->setObject((const OSSymbol *) o, tagString);// XXX check return 97c1dac77fSApple OSS Distributions tagString->release(); 98c1dac77fSApple OSS Distributions 99c1dac77fSApple OSS Distributions return false; 100c1dac77fSApple OSS Distributions } 101c1dac77fSApple OSS Distributions 102c1dac77fSApple OSS Distributions bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString) 103c1dac77fSApple OSS Distributions { 104c1dac77fSApple OSS Distributions 105c1dac77fSApple OSS Distributions if (!addChar('<')) return false; 106c1dac77fSApple OSS Distributions if (!addString(tagString)) return false; 107c1dac77fSApple OSS Distributions if (!addString(" ID=\"")) return false; 108c1dac77fSApple OSS Distributions if (!addString(((OSString *)tags->getObject((const OSSymbol *)o))->getCStringNoCopy())) 109c1dac77fSApple OSS Distributions return false; 110c1dac77fSApple OSS Distributions if (!addChar('\"')) return false; 111c1dac77fSApple OSS Distributions if (!addChar('>')) return false; 112c1dac77fSApple OSS Distributions return true; 113c1dac77fSApple OSS Distributions } 114c1dac77fSApple OSS Distributions 115c1dac77fSApple OSS Distributions bool OSSerialize::addXMLEndTag(const char *tagString) 116c1dac77fSApple OSS Distributions { 117c1dac77fSApple OSS Distributions 118c1dac77fSApple OSS Distributions if (!addChar('<')) return false; 119c1dac77fSApple OSS Distributions if (!addChar('/')) return false; 120c1dac77fSApple OSS Distributions if (!addString(tagString)) return false; 121c1dac77fSApple OSS Distributions if (!addChar('>')) return false; 122c1dac77fSApple OSS Distributions return true; 123c1dac77fSApple OSS Distributions } 124c1dac77fSApple OSS Distributions 125c1dac77fSApple OSS Distributions bool OSSerialize::addChar(const char c) 126c1dac77fSApple OSS Distributions { 127c1dac77fSApple OSS Distributions // add char, possibly extending our capacity 128c1dac77fSApple OSS Distributions if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement)) 129c1dac77fSApple OSS Distributions return false; 130c1dac77fSApple OSS Distributions 131c1dac77fSApple OSS Distributions data[length - 1] = c; 132c1dac77fSApple OSS Distributions length++; 133c1dac77fSApple OSS Distributions 134c1dac77fSApple OSS Distributions return true; 135c1dac77fSApple OSS Distributions } 136c1dac77fSApple OSS Distributions 137c1dac77fSApple OSS Distributions bool OSSerialize::addString(const char *s) 138c1dac77fSApple OSS Distributions { 139c1dac77fSApple OSS Distributions bool rc = false; 140c1dac77fSApple OSS Distributions 141c1dac77fSApple OSS Distributions while (*s && (rc = addChar(*s++))) ; 142c1dac77fSApple OSS Distributions 143c1dac77fSApple OSS Distributions return rc; 144c1dac77fSApple OSS Distributions } 145c1dac77fSApple OSS Distributions 146c1dac77fSApple OSS Distributions bool OSSerialize::initWithCapacity(unsigned int inCapacity) 147c1dac77fSApple OSS Distributions { 148c1dac77fSApple OSS Distributions if (!super::init()) 149c1dac77fSApple OSS Distributions return false; 150c1dac77fSApple OSS Distributions 151c1dac77fSApple OSS Distributions tags = OSDictionary::withCapacity(32); 152c1dac77fSApple OSS Distributions if (!tags) { 153c1dac77fSApple OSS Distributions return false; 154c1dac77fSApple OSS Distributions } 155c1dac77fSApple OSS Distributions 156c1dac77fSApple OSS Distributions tag = 0; 157c1dac77fSApple OSS Distributions length = 1; 158368ad365SApple OSS Distributions capacity = (inCapacity) ? round_page_32(inCapacity) : round_page_32(1); 159fad439e7SApple OSS Distributions capacityIncrement = capacity; 160c1dac77fSApple OSS Distributions 161fad439e7SApple OSS Distributions // allocate from the kernel map so that we can safely map this data 162fad439e7SApple OSS Distributions // into user space (the primary use of the OSSerialize object) 163fad439e7SApple OSS Distributions 164fad439e7SApple OSS Distributions kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity); 165fad439e7SApple OSS Distributions if (rc) { 166c1dac77fSApple OSS Distributions tags->release(); 167c1dac77fSApple OSS Distributions tags = 0; 168c1dac77fSApple OSS Distributions return false; 169c1dac77fSApple OSS Distributions } 170c1dac77fSApple OSS Distributions bzero((void *)data, capacity); 171c1dac77fSApple OSS Distributions 172c1dac77fSApple OSS Distributions 173c1dac77fSApple OSS Distributions ACCUMSIZE(capacity); 174c1dac77fSApple OSS Distributions 175c1dac77fSApple OSS Distributions return true; 176c1dac77fSApple OSS Distributions } 177c1dac77fSApple OSS Distributions 178c1dac77fSApple OSS Distributions OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity) 179c1dac77fSApple OSS Distributions { 180c1dac77fSApple OSS Distributions OSSerialize *me = new OSSerialize; 181c1dac77fSApple OSS Distributions 182c1dac77fSApple OSS Distributions if (me && !me->initWithCapacity(inCapacity)) { 183368ad365SApple OSS Distributions me->release(); 184c1dac77fSApple OSS Distributions return 0; 185c1dac77fSApple OSS Distributions } 186c1dac77fSApple OSS Distributions 187c1dac77fSApple OSS Distributions return me; 188c1dac77fSApple OSS Distributions } 189c1dac77fSApple OSS Distributions 190c1dac77fSApple OSS Distributions unsigned int OSSerialize::getLength() const { return length; } 191c1dac77fSApple OSS Distributions unsigned int OSSerialize::getCapacity() const { return capacity; } 192c1dac77fSApple OSS Distributions unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; } 193c1dac77fSApple OSS Distributions unsigned int OSSerialize::setCapacityIncrement(unsigned int increment) 194c1dac77fSApple OSS Distributions { 195c1dac77fSApple OSS Distributions capacityIncrement = (increment)? increment : 256; 196c1dac77fSApple OSS Distributions return capacityIncrement; 197c1dac77fSApple OSS Distributions } 198c1dac77fSApple OSS Distributions 199c1dac77fSApple OSS Distributions unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity) 200c1dac77fSApple OSS Distributions { 201c1dac77fSApple OSS Distributions char *newData; 202c1dac77fSApple OSS Distributions 203c1dac77fSApple OSS Distributions if (newCapacity <= capacity) 204c1dac77fSApple OSS Distributions return capacity; 205c1dac77fSApple OSS Distributions 206c1dac77fSApple OSS Distributions // round up 207368ad365SApple OSS Distributions newCapacity = round_page_32(newCapacity); 208c1dac77fSApple OSS Distributions 209fad439e7SApple OSS Distributions kern_return_t rc = kmem_realloc(kernel_map, 210fad439e7SApple OSS Distributions (vm_offset_t)data, 211fad439e7SApple OSS Distributions capacity, 212fad439e7SApple OSS Distributions (vm_offset_t *)&newData, 213fad439e7SApple OSS Distributions newCapacity); 214fad439e7SApple OSS Distributions if (!rc) { 215fad439e7SApple OSS Distributions ACCUMSIZE(newCapacity); 216c1dac77fSApple OSS Distributions 217fad439e7SApple OSS Distributions // kmem realloc does not free the old address range 218fad439e7SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity); 219fad439e7SApple OSS Distributions ACCUMSIZE(-capacity); 220fad439e7SApple OSS Distributions 221fad439e7SApple OSS Distributions // kmem realloc does not zero out the new memory 222fad439e7SApple OSS Distributions // and this could end up going to user land 223fad439e7SApple OSS Distributions bzero(&newData[capacity], newCapacity - capacity); 224fad439e7SApple OSS Distributions 225c1dac77fSApple OSS Distributions data = newData; 226c1dac77fSApple OSS Distributions capacity = newCapacity; 227c1dac77fSApple OSS Distributions } 228c1dac77fSApple OSS Distributions 229c1dac77fSApple OSS Distributions return capacity; 230c1dac77fSApple OSS Distributions } 231c1dac77fSApple OSS Distributions 232c1dac77fSApple OSS Distributions void OSSerialize::free() 233c1dac77fSApple OSS Distributions { 234c1dac77fSApple OSS Distributions if (tags) 235c1dac77fSApple OSS Distributions tags->release(); 236c1dac77fSApple OSS Distributions 237c1dac77fSApple OSS Distributions if (data) { 238fad439e7SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t)data, capacity); 239c1dac77fSApple OSS Distributions ACCUMSIZE( -capacity ); 240c1dac77fSApple OSS Distributions } 241c1dac77fSApple OSS Distributions super::free(); 242c1dac77fSApple OSS Distributions } 243c1dac77fSApple OSS Distributions 244c1dac77fSApple OSS Distributions 245c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(OSSerializer, OSObject) 246c1dac77fSApple OSS Distributions 247c1dac77fSApple OSS Distributions OSSerializer * OSSerializer::forTarget( void * target, 248368ad365SApple OSS Distributions OSSerializerCallback callback, void * ref ) 249c1dac77fSApple OSS Distributions { 250c1dac77fSApple OSS Distributions OSSerializer * thing; 251c1dac77fSApple OSS Distributions 252c1dac77fSApple OSS Distributions thing = new OSSerializer; 253c1dac77fSApple OSS Distributions if( thing && !thing->init()) { 254c1dac77fSApple OSS Distributions thing->release(); 255c1dac77fSApple OSS Distributions thing = 0; 256c1dac77fSApple OSS Distributions } 257c1dac77fSApple OSS Distributions 258c1dac77fSApple OSS Distributions if( thing) { 259c1dac77fSApple OSS Distributions thing->target = target; 260c1dac77fSApple OSS Distributions thing->ref = ref; 261c1dac77fSApple OSS Distributions thing->callback = callback; 262c1dac77fSApple OSS Distributions } 263c1dac77fSApple OSS Distributions return( thing ); 264c1dac77fSApple OSS Distributions } 265c1dac77fSApple OSS Distributions 266c1dac77fSApple OSS Distributions bool OSSerializer::serialize( OSSerialize * s ) const 267c1dac77fSApple OSS Distributions { 268c1dac77fSApple OSS Distributions return( (*callback)(target, ref, s) ); 269c1dac77fSApple OSS Distributions } 270