2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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. 
  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 
  20  * @APPLE_LICENSE_HEADER_END@ 
  22 /* IOData.m created by rsulack on Thu 25-Sep-1997 */ 
  26 #include <libkern/c++/OSData.h> 
  27 #include <libkern/c++/OSSerialize.h> 
  28 #include <libkern/c++/OSLib.h> 
  29 #include <libkern/c++/OSString.h> 
  32 #define super OSObject 
  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); 
  44 #define EXTERNAL ((unsigned int) -1) 
  47 extern int debug_container_malloc_size
; 
  48 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 
  53 bool OSData::initWithCapacity(unsigned int inCapacity
) 
  58     if (data 
&& (!inCapacity 
|| capacity 
< inCapacity
) ) { 
  59         // clean out old data's storage if it isn't big enough 
  60         kfree(data
, capacity
); 
  65     if (inCapacity 
&& !data
) { 
  66         data 
= (void *) kalloc(inCapacity
); 
  69         capacity 
= inCapacity
; 
  70         ACCUMSIZE(inCapacity
); 
  75         capacityIncrement 
= 16; 
  77         capacityIncrement 
= inCapacity
; 
  82 bool OSData::initWithBytes(const void *bytes
, unsigned int inLength
) 
  84     if ((inLength 
&& !bytes
) || !initWithCapacity(inLength
)) 
  88         bcopy(bytes
, data
, inLength
); 
  94 bool OSData::initWithBytesNoCopy(void *bytes
, unsigned int inLength
) 
 106 bool OSData::initWithData(const OSData 
*inData
) 
 108     return initWithBytes(inData
->data
, inData
->length
); 
 111 bool OSData::initWithData(const OSData 
*inData
, 
 112                           unsigned int start
, unsigned int inLength
) 
 114     const void *localData 
= inData
->getBytesNoCopy(start
, inLength
); 
 117         return initWithBytes(localData
, inLength
); 
 122 OSData 
*OSData::withCapacity(unsigned int inCapacity
) 
 124     OSData 
*me 
= new OSData
; 
 126     if (me 
&& !me
->initWithCapacity(inCapacity
)) { 
 134 OSData 
*OSData::withBytes(const void *bytes
, unsigned int inLength
) 
 136     OSData 
*me 
= new OSData
; 
 138     if (me 
&& !me
->initWithBytes(bytes
, inLength
)) { 
 145 OSData 
*OSData::withBytesNoCopy(void *bytes
, unsigned int inLength
) 
 147     OSData 
*me 
= new OSData
; 
 149     if (me 
&& !me
->initWithBytesNoCopy(bytes
, inLength
)) { 
 157 OSData 
*OSData::withData(const OSData 
*inData
) 
 159     OSData 
*me 
= new OSData
; 
 161     if (me 
&& !me
->initWithData(inData
)) { 
 169 OSData 
*OSData::withData(const OSData 
*inData
, 
 170                          unsigned int start
, unsigned int inLength
) 
 172     OSData 
*me 
= new OSData
; 
 174     if (me 
&& !me
->initWithData(inData
, start
, inLength
)) { 
 184     if (capacity 
!= EXTERNAL 
&& data 
&& capacity
) { 
 185         kfree(data
, capacity
); 
 186         ACCUMSIZE( -capacity 
); 
 191 unsigned int OSData::getLength() const { return length
; } 
 192 unsigned int OSData::getCapacity() const { return capacity
; } 
 194 unsigned int OSData::getCapacityIncrement() const  
 196     return capacityIncrement
;  
 199 unsigned int OSData::setCapacityIncrement(unsigned increment
)  
 201     return capacityIncrement 
= increment
;  
 204 unsigned int OSData::ensureCapacity(unsigned int newCapacity
) 
 206     unsigned char * newData
; 
 208     if (newCapacity 
<= capacity
) 
 211     newCapacity 
= (((newCapacity 
- 1) / capacityIncrement
) + 1) 
 214     newData 
= (unsigned char *) kalloc(newCapacity
); 
 217         bzero(newData 
+ capacity
, newCapacity 
- capacity
); 
 219             bcopy(data
, newData
, capacity
); 
 220             kfree(data
, capacity
); 
 222         ACCUMSIZE( newCapacity 
- capacity 
); 
 223         data 
= (void *) newData
; 
 224         capacity 
= newCapacity
; 
 230 bool OSData::appendBytes(const void *bytes
, unsigned int inLength
) 
 232     unsigned int newSize
; 
 237     if (capacity 
== EXTERNAL
) 
 240     newSize 
= length 
+ inLength
; 
 241     if ( (newSize 
> capacity
) && newSize 
> ensureCapacity(newSize
) ) 
 245         bcopy(bytes
, &((unsigned char *)data
)[length
], inLength
); 
 247         bzero(&((unsigned char *)data
)[length
], inLength
); 
 254 bool OSData::appendByte(unsigned char byte
, unsigned int inLength
) 
 256     unsigned int newSize
; 
 261     if (capacity 
== EXTERNAL
) 
 264     newSize 
= length 
+ inLength
; 
 265     if ( (newSize 
> capacity
) && newSize 
> ensureCapacity(newSize
) ) 
 268     memset(&((unsigned char *)data
)[length
], byte
, inLength
); 
 274 bool OSData::appendBytes(const OSData 
*other
) 
 276     return appendBytes(other
->data
, other
->length
); 
 279 const void *OSData::getBytesNoCopy() const 
 287 const void *OSData::getBytesNoCopy(unsigned int start
, 
 288                                    unsigned int inLength
) const 
 290     const void *outData 
= 0; 
 294     && (start 
+ inLength
) <= length
) 
 295         outData 
= (const void *) ((char *) data 
+ start
); 
 300 bool OSData::isEqualTo(const OSData 
*aData
) const 
 308     return isEqualTo(aData
->data
, len
); 
 311 bool OSData::isEqualTo(const void *someData
, unsigned int inLength
) const 
 313     return (length 
>= inLength
) && (bcmp(data
, someData
, inLength
) == 0); 
 316 bool OSData::isEqualTo(const OSMetaClassBase 
*obj
) const 
 321     if ((data 
= OSDynamicCast(OSData
, obj
))) 
 322         return isEqualTo(data
); 
 323     else if ((str 
= OSDynamicCast (OSString
, obj
))) 
 324         return isEqualTo(str
); 
 329 bool OSData::isEqualTo(const OSString 
*obj
) const 
 331     const char * aCString
; 
 333     unsigned int checkLen 
= length
; 
 334     unsigned int stringLen
; 
 339     stringLen 
= obj
->getLength (); 
 341     dataPtr 
= (char *)data
; 
 343     if (stringLen 
!= checkLen
) { 
 345       // check for the fact that OSData may be a buffer that 
 346       // that includes a termination byte and will thus have 
 347       // a length of the actual string length PLUS 1. In this 
 348       // case we verify that the additional byte is a terminator 
 349       // and if so count the two lengths as being the same. 
 351       if ( (checkLen 
- stringLen
) == 1) { 
 352         if (dataPtr
[checkLen
-1] != 0) // non-zero means not a terminator and thus not likely the same 
 360     aCString 
= obj
->getCStringNoCopy (); 
 362     for ( unsigned int i
=0; i 
< checkLen
; i
++ ) { 
 363       if ( *dataPtr
++ != aCString
[i
] )  
 370 //this was taken from CFPropertyList.c  
 371 static const char __CFPLDataEncodeTable
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
 373 bool OSData::serialize(OSSerialize 
*s
) const 
 376     const unsigned char *p
; 
 379     if (s
->previouslySerialized(this)) return true; 
 381     if (!s
->addXMLStartTag(this, "data")) return false; 
 383     for (i 
= 0, p 
= (unsigned char *)data
; i 
< length
; i
++, p
++) { 
 384         /* 3 bytes are encoded as 4 */ 
 387                 c 
= __CFPLDataEncodeTable 
[ ((p
[0] >> 2) & 0x3f)]; 
 388                 if (!s
->addChar(c
)) return false; 
 391                 c 
= __CFPLDataEncodeTable 
[ ((((p
[-1] << 8) | p
[0]) >> 4) & 0x3f)]; 
 392                 if (!s
->addChar(c
)) return false; 
 395                 c 
= __CFPLDataEncodeTable 
[ ((((p
[-1] << 8) | p
[0]) >> 6) & 0x3f)]; 
 396                 if (!s
->addChar(c
)) return false; 
 397                 c 
= __CFPLDataEncodeTable 
[ (p
[0] & 0x3f)]; 
 398                 if (!s
->addChar(c
)) return false; 
 406             c 
= __CFPLDataEncodeTable 
[ ((p
[-1] << 4) & 0x30)]; 
 407             if (!s
->addChar(c
)) return false; 
 408             if (!s
->addChar('=')) return false; 
 409             if (!s
->addChar('=')) return false; 
 412             c 
= __CFPLDataEncodeTable 
[ ((p
[-1] << 2) & 0x3c)]; 
 413             if (!s
->addChar(c
)) return false; 
 414             if (!s
->addChar('=')) return false; 
 418     return s
->addXMLEndTag("data");