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