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