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 /* IOData.m created by rsulack on Thu 25-Sep-1997 */ 23 24 25 #include <libkern/c++/OSData.h> 26 #include <libkern/c++/OSSerialize.h> 27 #include <libkern/c++/OSLib.h> 28 #include <libkern/c++/OSString.h> 29 30 #define super OSObject 31 32 OSDefineMetaClassAndStructors(OSData, OSObject) 33 OSMetaClassDefineReservedUnused(OSData, 0); 34 OSMetaClassDefineReservedUnused(OSData, 1); 35 OSMetaClassDefineReservedUnused(OSData, 2); 36 OSMetaClassDefineReservedUnused(OSData, 3); 37 OSMetaClassDefineReservedUnused(OSData, 4); 38 OSMetaClassDefineReservedUnused(OSData, 5); 39 OSMetaClassDefineReservedUnused(OSData, 6); 40 OSMetaClassDefineReservedUnused(OSData, 7); 41 42 #define EXTERNAL ((unsigned int) -1) 43 44 #if OSALLOCDEBUG 45 extern "C" { 46 extern int debug_container_malloc_size; 47 }; 48 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 49 #else 50 #define ACCUMSIZE(s) 51 #endif 52 53 bool OSData::initWithCapacity(unsigned int inCapacity) 54 { 55 if (!super::init()) 56 return false; 57 58 if(inCapacity) { 59 data = (void *) kalloc(inCapacity); 60 if (!data) 61 return false; 62 } 63 64 length = 0; 65 capacity = inCapacity; 66 capacityIncrement = capacity; 67 if(!capacityIncrement) 68 capacityIncrement = 16; 69 70 ACCUMSIZE(capacity); 71 72 return true; 73 } 74 75 bool OSData::initWithBytes(const void *bytes, unsigned int inLength) 76 { 77 if ((inLength && !bytes) || !initWithCapacity(inLength)) 78 return false; 79 80 bcopy(bytes, data, inLength); 81 length = inLength; 82 83 return true; 84 } 85 86 bool OSData::initWithBytesNoCopy(void *bytes, unsigned int inLength) 87 { 88 if (!super::init()) 89 return false; 90 91 length = inLength; 92 capacity = EXTERNAL; 93 data = bytes; 94 95 return true; 96 } 97 98 bool OSData::initWithData(const OSData *inData) 99 { 100 return initWithBytes(inData->data, inData->length); 101 } 102 103 bool OSData::initWithData(const OSData *inData, 104 unsigned int start, unsigned int inLength) 105 { 106 const void *localData = inData->getBytesNoCopy(start, inLength); 107 108 if (localData) 109 return initWithBytes(localData, inLength); 110 else 111 return false; 112 } 113 114 OSData *OSData::withCapacity(unsigned int inCapacity) 115 { 116 OSData *me = new OSData; 117 118 if (me && !me->initWithCapacity(inCapacity)) { 119 me->free(); 120 return 0; 121 } 122 123 return me; 124 } 125 126 OSData *OSData::withBytes(const void *bytes, unsigned int inLength) 127 { 128 OSData *me = new OSData; 129 130 if (me && !me->initWithBytes(bytes, inLength)) { 131 me->free(); 132 return 0; 133 } 134 return me; 135 } 136 137 OSData *OSData::withBytesNoCopy(void *bytes, unsigned int inLength) 138 { 139 OSData *me = new OSData; 140 141 if (me && !me->initWithBytesNoCopy(bytes, inLength)) { 142 me->free(); 143 return 0; 144 } 145 146 return me; 147 } 148 149 OSData *OSData::withData(const OSData *inData) 150 { 151 OSData *me = new OSData; 152 153 if (me && !me->initWithData(inData)) { 154 me->free(); 155 return 0; 156 } 157 158 return me; 159 } 160 161 OSData *OSData::withData(const OSData *inData, 162 unsigned int start, unsigned int inLength) 163 { 164 OSData *me = new OSData; 165 166 if (me && !me->initWithData(inData, start, inLength)) { 167 me->free(); 168 return 0; 169 } 170 171 return me; 172 } 173 174 void OSData::free() 175 { 176 if (capacity != EXTERNAL && data && capacity) { 177 kfree((vm_offset_t)data, capacity); 178 ACCUMSIZE( -capacity ); 179 } 180 super::free(); 181 } 182 183 unsigned int OSData::getLength() const { return length; } 184 unsigned int OSData::getCapacity() const { return capacity; } 185 186 unsigned int OSData::getCapacityIncrement() const 187 { 188 return capacityIncrement; 189 } 190 191 unsigned int OSData::setCapacityIncrement(unsigned increment) 192 { 193 return capacityIncrement = increment; 194 } 195 196 unsigned int OSData::ensureCapacity(unsigned int newCapacity) 197 { 198 unsigned char * newData; 199 200 if (newCapacity <= capacity) 201 return capacity; 202 203 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) 204 * capacityIncrement; 205 206 newData = (unsigned char *) kalloc(newCapacity); 207 208 if ( newData ) { 209 bzero(newData + capacity, newCapacity - capacity); 210 if (data) { 211 bcopy(data, newData, capacity); 212 kfree((vm_offset_t)data, capacity); 213 } 214 ACCUMSIZE( newCapacity - capacity ); 215 data = (void *) newData; 216 capacity = newCapacity; 217 } 218 219 return capacity; 220 } 221 222 bool OSData::appendBytes(const void *bytes, unsigned int inLength) 223 { 224 unsigned int newSize; 225 226 if (inLength == 0) 227 return true; 228 229 if (capacity == EXTERNAL) 230 return false; 231 232 newSize = length + inLength; 233 if ( (newSize > capacity) && newSize > ensureCapacity(newSize) ) 234 return false; 235 236 bcopy(bytes, &((unsigned char *)data)[length], inLength); 237 length = newSize; 238 239 return true; 240 } 241 242 bool OSData::appendByte(unsigned char byte, unsigned int inLength) 243 { 244 unsigned int newSize; 245 246 if (inLength == 0) 247 return true; 248 249 if (capacity == EXTERNAL) 250 return false; 251 252 newSize = length + inLength; 253 if ( (newSize > capacity) && newSize > ensureCapacity(newSize) ) 254 return false; 255 256 memset(&((unsigned char *)data)[length], byte, inLength); 257 length = newSize; 258 259 return true; 260 } 261 262 bool OSData::appendBytes(const OSData *other) 263 { 264 return appendBytes(other->data, other->length); 265 } 266 267 const void *OSData::getBytesNoCopy() const 268 { 269 if (length == 0) 270 return 0; 271 else 272 return data; 273 } 274 275 const void *OSData::getBytesNoCopy(unsigned int start, 276 unsigned int inLength) const 277 { 278 const void *outData = 0; 279 280 if (length 281 && start < length 282 && (start + inLength) <= length) 283 outData = (const void *) ((char *) data + start); 284 285 return outData; 286 } 287 288 bool OSData::isEqualTo(const OSData *aData) const 289 { 290 unsigned int len; 291 292 len = aData->length; 293 if ( length != len ) 294 return false; 295 296 return isEqualTo(aData->data, len); 297 } 298 299 bool OSData::isEqualTo(const void *someData, unsigned int inLength) const 300 { 301 return (length >= inLength) && (bcmp(data, someData, inLength) == 0); 302 } 303 304 bool OSData::isEqualTo(const OSMetaClassBase *obj) const 305 { 306 OSData * data; 307 OSString * str; 308 309 if ((data = OSDynamicCast(OSData, obj))) 310 return isEqualTo(data); 311 else if ((str = OSDynamicCast (OSString, obj))) 312 return isEqualTo(str); 313 else 314 return false; 315 } 316 317 bool OSData::isEqualTo(const OSString *obj) const 318 { 319 const char * aCString; 320 char * dataPtr; 321 unsigned int checkLen = length; 322 unsigned int stringLen; 323 324 if (NULL == obj) 325 return false; 326 327 stringLen = obj->getLength (); 328 329 dataPtr = (char *)data; 330 331 if (stringLen != checkLen) { 332 333 // check for the fact that OSData may be a buffer that 334 // that includes a termination byte and will thus have 335 // a length of the actual string length PLUS 1. In this 336 // case we verify that the additional byte is a terminator 337 // and if so count the two lengths as being the same. 338 339 if ( (checkLen - stringLen) == 1) { 340 if (dataPtr[checkLen-1] != 0) // non-zero means not a terminator and thus not likely the same 341 return false; 342 checkLen--; 343 } 344 else 345 return false; 346 } 347 348 aCString = obj->getCStringNoCopy (); 349 350 for ( unsigned int i=0; i < checkLen; i++ ) { 351 if ( *dataPtr++ != aCString[i] ) 352 return false; 353 } 354 355 return true; 356 } 357 358 //this was taken from CFPropertyList.c 359 static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 360 361 bool OSData::serialize(OSSerialize *s) const 362 { 363 unsigned int i; 364 const unsigned char *p; 365 unsigned char c; 366 367 if (s->previouslySerialized(this)) return true; 368 369 if (!s->addXMLStartTag(this, "data")) return false; 370 371 for (i = 0, p = (unsigned char *)data; i < length; i++, p++) { 372 /* 3 bytes are encoded as 4 */ 373 switch (i % 3) { 374 case 0: 375 c = __CFPLDataEncodeTable [ ((p[0] >> 2) & 0x3f)]; 376 if (!s->addChar(c)) return false; 377 break; 378 case 1: 379 c = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 4) & 0x3f)]; 380 if (!s->addChar(c)) return false; 381 break; 382 case 2: 383 c = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 6) & 0x3f)]; 384 if (!s->addChar(c)) return false; 385 c = __CFPLDataEncodeTable [ (p[0] & 0x3f)]; 386 if (!s->addChar(c)) return false; 387 break; 388 } 389 } 390 switch (i % 3) { 391 case 0: 392 break; 393 case 1: 394 c = __CFPLDataEncodeTable [ ((p[-1] << 4) & 0x30)]; 395 if (!s->addChar(c)) return false; 396 if (!s->addChar('=')) return false; 397 if (!s->addChar('=')) return false; 398 break; 399 case 2: 400 c = __CFPLDataEncodeTable [ ((p[-1] << 2) & 0x3c)]; 401 if (!s->addChar(c)) return false; 402 if (!s->addChar('=')) return false; 403 break; 404 } 405 406 return s->addXMLEndTag("data"); 407 } 408