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