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 <libkern/c++/OSContainers.h> 25 #include <libkern/c++/OSLib.h> 26 #include <libkern/c++/OSDictionary.h> 27 28 #define super OSObject 29 30 OSDefineMetaClassAndStructors(OSSerialize, OSObject) 31 OSMetaClassDefineReservedUnused(OSSerialize, 0); 32 OSMetaClassDefineReservedUnused(OSSerialize, 1); 33 OSMetaClassDefineReservedUnused(OSSerialize, 2); 34 OSMetaClassDefineReservedUnused(OSSerialize, 3); 35 OSMetaClassDefineReservedUnused(OSSerialize, 4); 36 OSMetaClassDefineReservedUnused(OSSerialize, 5); 37 OSMetaClassDefineReservedUnused(OSSerialize, 6); 38 OSMetaClassDefineReservedUnused(OSSerialize, 7); 39 40 #if OSALLOCDEBUG 41 extern "C" { 42 extern int debug_container_malloc_size; 43 }; 44 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 45 #else 46 #define ACCUMSIZE(s) 47 #endif 48 49 char * OSSerialize::text() const 50 { 51 return data; 52 } 53 54 void OSSerialize::clearText() 55 { 56 bzero((void *)data, capacity); 57 length = 1; 58 tag = 0; 59 tags->flushCollection(); 60 } 61 62 bool OSSerialize::previouslySerialized(const OSMetaClassBase *o) 63 { 64 char temp[16]; 65 OSString *tagString; 66 67 // look it up 68 tagString = (OSString *)tags->getObject((const OSSymbol *) o); 69 70 // does it exist? 71 if (tagString) { 72 addString("<reference IDREF=\""); 73 addString(tagString->getCStringNoCopy()); 74 addString("\"/>"); 75 return true; 76 } 77 78 // build a tag 79 sprintf(temp, "%u", tag++); 80 tagString = OSString::withCString(temp); 81 82 // add to tag dictionary 83 tags->setObject((const OSSymbol *) o, tagString);// XXX check return 84 tagString->release(); 85 86 return false; 87 } 88 89 bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString) 90 { 91 92 if (!addChar('<')) return false; 93 if (!addString(tagString)) return false; 94 if (!addString(" ID=\"")) return false; 95 if (!addString(((OSString *)tags->getObject((const OSSymbol *)o))->getCStringNoCopy())) 96 return false; 97 if (!addChar('\"')) return false; 98 if (!addChar('>')) return false; 99 return true; 100 } 101 102 bool OSSerialize::addXMLEndTag(const char *tagString) 103 { 104 105 if (!addChar('<')) return false; 106 if (!addChar('/')) return false; 107 if (!addString(tagString)) return false; 108 if (!addChar('>')) return false; 109 return true; 110 } 111 112 bool OSSerialize::addChar(const char c) 113 { 114 // add char, possibly extending our capacity 115 if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement)) 116 return false; 117 118 data[length - 1] = c; 119 length++; 120 121 return true; 122 } 123 124 bool OSSerialize::addString(const char *s) 125 { 126 bool rc = false; 127 128 while (*s && (rc = addChar(*s++))) ; 129 130 return rc; 131 } 132 133 bool OSSerialize::initWithCapacity(unsigned int inCapacity) 134 { 135 if (!super::init()) 136 return false; 137 138 tags = OSDictionary::withCapacity(32); 139 if (!tags) { 140 return false; 141 } 142 143 tag = 0; 144 length = 1; 145 capacity = inCapacity; 146 capacityIncrement = (capacity)? capacity : 256; 147 148 capacity = (((capacity - 1) / capacityIncrement) + 1) 149 * capacityIncrement; 150 data = (char *) kalloc(capacity); 151 if (!data) { 152 tags->release(); 153 tags = 0; 154 return false; 155 } 156 bzero((void *)data, capacity); 157 158 159 ACCUMSIZE(capacity); 160 161 return true; 162 } 163 164 OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity) 165 { 166 OSSerialize *me = new OSSerialize; 167 168 if (me && !me->initWithCapacity(inCapacity)) { 169 me->free(); 170 return 0; 171 } 172 173 return me; 174 } 175 176 unsigned int OSSerialize::getLength() const { return length; } 177 unsigned int OSSerialize::getCapacity() const { return capacity; } 178 unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; } 179 unsigned int OSSerialize::setCapacityIncrement(unsigned int increment) 180 { 181 capacityIncrement = (increment)? increment : 256; 182 return capacityIncrement; 183 } 184 185 unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity) 186 { 187 char *newData; 188 unsigned int oldCapacity; 189 190 if (newCapacity <= capacity) 191 return capacity; 192 193 // round up 194 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) 195 * capacityIncrement; 196 newData = (char *) kalloc(newCapacity); 197 if (newData) { 198 oldCapacity = capacity; 199 200 ACCUMSIZE(newCapacity - oldCapacity); 201 202 bcopy(data, newData, oldCapacity); 203 bzero(&newData[capacity], newCapacity - oldCapacity); 204 kfree((vm_offset_t)data, oldCapacity); 205 data = newData; 206 capacity = newCapacity; 207 } 208 209 return capacity; 210 } 211 212 void OSSerialize::free() 213 { 214 if (tags) 215 tags->release(); 216 217 if (data) { 218 kfree((vm_offset_t)data, capacity); 219 ACCUMSIZE( -capacity ); 220 } 221 super::free(); 222 } 223 224 225 OSDefineMetaClassAndStructors(OSSerializer, OSObject) 226 227 OSSerializer * OSSerializer::forTarget( void * target, 228 OSSerializerCallback callback, void * ref = 0 ) 229 { 230 OSSerializer * thing; 231 232 thing = new OSSerializer; 233 if( thing && !thing->init()) { 234 thing->release(); 235 thing = 0; 236 } 237 238 if( thing) { 239 thing->target = target; 240 thing->ref = ref; 241 thing->callback = callback; 242 } 243 return( thing ); 244 } 245 246 bool OSSerializer::serialize( OSSerialize * s ) const 247 { 248 return( (*callback)(target, ref, s) ); 249 } 250