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) 
  48     extern int debug_container_malloc_size
; 
  50 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 
  55 bool OSData::initWithCapacity(unsigned int inCapacity
) 
  61         data 
= (void *) kalloc(inCapacity
); 
  67     capacity 
= inCapacity
; 
  68     capacityIncrement 
= capacity
; 
  69     if(!capacityIncrement
) 
  70         capacityIncrement 
= 16; 
  77 bool OSData::initWithBytes(const void *bytes
, unsigned int inLength
) 
  79     if ((inLength 
&& !bytes
) || !initWithCapacity(inLength
)) 
  82     bcopy(bytes
, data
, inLength
); 
  88 bool OSData::initWithBytesNoCopy(void *bytes
, unsigned int inLength
) 
 100 bool OSData::initWithData(const OSData 
*inData
) 
 102     return initWithBytes(inData
->data
, inData
->length
); 
 105 bool OSData::initWithData(const OSData 
*inData
, 
 106                           unsigned int start
, unsigned int inLength
) 
 108     const void *localData 
= inData
->getBytesNoCopy(start
, inLength
); 
 111         return initWithBytes(localData
, inLength
); 
 116 OSData 
*OSData::withCapacity(unsigned int inCapacity
) 
 118     OSData 
*me 
= new OSData
; 
 120     if (me 
&& !me
->initWithCapacity(inCapacity
)) { 
 128 OSData 
*OSData::withBytes(const void *bytes
, unsigned int inLength
) 
 130     OSData 
*me 
= new OSData
; 
 132     if (me 
&& !me
->initWithBytes(bytes
, inLength
)) { 
 139 OSData 
*OSData::withBytesNoCopy(void *bytes
, unsigned int inLength
) 
 141     OSData 
*me 
= new OSData
; 
 143     if (me 
&& !me
->initWithBytesNoCopy(bytes
, inLength
)) { 
 151 OSData 
*OSData::withData(const OSData 
*inData
) 
 153     OSData 
*me 
= new OSData
; 
 155     if (me 
&& !me
->initWithData(inData
)) { 
 163 OSData 
*OSData::withData(const OSData 
*inData
, 
 164                          unsigned int start
, unsigned int inLength
) 
 166     OSData 
*me 
= new OSData
; 
 168     if (me 
&& !me
->initWithData(inData
, start
, inLength
)) { 
 178     if (capacity 
!= EXTERNAL 
&& data 
&& capacity
) { 
 179         kfree((vm_offset_t
)data
, capacity
); 
 180         ACCUMSIZE( -capacity 
); 
 185 unsigned int OSData::getLength() const { return length
; } 
 186 unsigned int OSData::getCapacity() const { return capacity
; } 
 188 unsigned int OSData::getCapacityIncrement() const  
 190     return capacityIncrement
;  
 193 unsigned int OSData::setCapacityIncrement(unsigned increment
)  
 195     return capacityIncrement 
= increment
;  
 198 unsigned int OSData::ensureCapacity(unsigned int newCapacity
) 
 200     unsigned char * newData
; 
 202     if (newCapacity 
<= capacity
) 
 205     newCapacity 
= (((newCapacity 
- 1) / capacityIncrement
) + 1) 
 208     newData 
= (unsigned char *) kalloc(newCapacity
); 
 211         bzero(newData 
+ capacity
, newCapacity 
- capacity
); 
 213             bcopy(data
, newData
, capacity
); 
 214             kfree((vm_offset_t
)data
, capacity
); 
 216         ACCUMSIZE( newCapacity 
- capacity 
); 
 217         data 
= (void *) newData
; 
 218         capacity 
= newCapacity
; 
 224 bool OSData::appendBytes(const void *bytes
, unsigned int inLength
) 
 226     unsigned int newSize
; 
 231     if (capacity 
== EXTERNAL
) 
 234     newSize 
= length 
+ inLength
; 
 235     if ( (newSize 
> capacity
) && newSize 
> ensureCapacity(newSize
) ) 
 238     bcopy(bytes
, &((unsigned char *)data
)[length
], inLength
); 
 244 bool OSData::appendByte(unsigned char byte
, unsigned int inLength
) 
 246     unsigned int newSize
; 
 251     if (capacity 
== EXTERNAL
) 
 254     newSize 
= length 
+ inLength
; 
 255     if ( (newSize 
> capacity
) && newSize 
> ensureCapacity(newSize
) ) 
 258     memset(&((unsigned char *)data
)[length
], byte
, inLength
); 
 264 bool OSData::appendBytes(const OSData 
*other
) 
 266     return appendBytes(other
->data
, other
->length
); 
 269 const void *OSData::getBytesNoCopy() const 
 277 const void *OSData::getBytesNoCopy(unsigned int start
, 
 278                                    unsigned int inLength
) const 
 280     const void *outData 
= 0; 
 284     && (start 
+ inLength
) <= length
) 
 285         outData 
= (const void *) ((char *) data 
+ start
); 
 290 bool OSData::isEqualTo(const OSData 
*aData
) const 
 298     return isEqualTo(aData
->data
, len
); 
 301 bool OSData::isEqualTo(const void *someData
, unsigned int inLength
) const 
 303     return (length 
>= inLength
) && (bcmp(data
, someData
, inLength
) == 0); 
 306 bool OSData::isEqualTo(const OSMetaClassBase 
*obj
) const 
 311     if ((data 
= OSDynamicCast(OSData
, obj
))) 
 312         return isEqualTo(data
); 
 313     else if ((str 
= OSDynamicCast (OSString
, obj
))) 
 314         return isEqualTo(str
); 
 319 bool OSData::isEqualTo(const OSString 
*obj
) const 
 321     const char * aCString
; 
 323     unsigned int checkLen 
= length
; 
 324     unsigned int stringLen
; 
 329     stringLen 
= obj
->getLength (); 
 331     dataPtr 
= (char *)data
; 
 333     if (stringLen 
!= checkLen
) { 
 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. 
 341       if ( (checkLen 
- stringLen
) == 1) { 
 342         if (dataPtr
[checkLen
-1] != 0) // non-zero means not a terminator and thus not likely the same 
 350     aCString 
= obj
->getCStringNoCopy (); 
 352     for ( unsigned int i
=0; i 
< checkLen
; i
++ ) { 
 353       if ( *dataPtr
++ != aCString
[i
] )  
 360 //this was taken from CFPropertyList.c  
 361 static const char __CFPLDataEncodeTable
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
 363 bool OSData::serialize(OSSerialize 
*s
) const 
 366     const unsigned char *p
; 
 369     if (s
->previouslySerialized(this)) return true; 
 371     if (!s
->addXMLStartTag(this, "data")) return false; 
 373     for (i 
= 0, p 
= (unsigned char *)data
; i 
< length
; i
++, p
++) { 
 374         /* 3 bytes are encoded as 4 */ 
 377                 c 
= __CFPLDataEncodeTable 
[ ((p
[0] >> 2) & 0x3f)]; 
 378                 if (!s
->addChar(c
)) return false; 
 381                 c 
= __CFPLDataEncodeTable 
[ ((((p
[-1] << 8) | p
[0]) >> 4) & 0x3f)]; 
 382                 if (!s
->addChar(c
)) return false; 
 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; 
 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; 
 402             c 
= __CFPLDataEncodeTable 
[ ((p
[-1] << 2) & 0x3c)]; 
 403             if (!s
->addChar(c
)) return false; 
 404             if (!s
->addChar('=')) return false; 
 408     return s
->addXMLEndTag("data");