File:  [Apple XNU] / XNU / libkern / c++ / OSArray.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:45:09 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: v68_4-1_1, HEAD
xnu-68.4-1.1

/*
 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 * 
 * This Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/* IOArray.m created by rsulack on Fri 12-Sep-1997 */
/* IOArray.cpp converted to C++ by gvdl on Fri 1998-10-30 */


#include <libkern/c++/OSArray.h>
#include <libkern/c++/OSSerialize.h>
#include <libkern/c++/OSLib.h>

#define super OSCollection

OSDefineMetaClassAndStructors(OSArray, OSCollection)


#ifdef DEBUG
extern "C" {
    extern int debug_container_malloc_size;
};
#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
#else
#define ACCUMSIZE(s)
#endif

bool OSArray::initWithCapacity(unsigned int inCapacity)
{
    int size;

    if (!super::init())
        return false;

    size = sizeof(OSObject *) * inCapacity;
    array = (OSObject **) kalloc(size);
    if (!array)
        return false;

    count = 0;
    capacity = inCapacity;
    capacityIncrement = capacity;

    bzero(array, size);
    ACCUMSIZE(size);

    return this;	
}

bool OSArray::initWithObjects(OSObject *objects[],
                              unsigned int theCount,
                              unsigned int theCapacity = 0)
{
    unsigned int capacity = theCount;

    if ( theCapacity ) {
        if ( theCount > theCapacity )
            return false;

        capacity = theCapacity;
    }

    if (!objects || !initWithCapacity(capacity))
        return false;

    for ( unsigned int i = 0; i < theCount; i++ ) {
        OSObject *newObject = *objects++;

        if (!newObject)
            return false;

        array[count++] = newObject;
        newObject->retain();
    }

    return true;	
}

bool OSArray::initWithArray(const OSArray *anArray,
                            unsigned int theCapacity = 0)
{
    if ( !anArray )
        return false;

    return initWithObjects(anArray->array, anArray->count,
                           theCapacity);
}

OSArray *OSArray::withCapacity(unsigned int capacity)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithCapacity(capacity)) {
        me->free();
        return 0;
    }

    return me;
}

OSArray *OSArray::withObjects(OSObject *objects[],
                              unsigned int count,
                              unsigned int capacity = 0)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithObjects(objects, count, capacity)) {
        me->free();
        return 0;
    }

    return me;
}

OSArray *OSArray::withArray(const OSArray *array,
                            unsigned int capacity = 0)
{
    OSArray *me = new OSArray;

    if (me && !me->initWithArray(array, capacity)) {
        me->free();
        return 0;
    }

    return me;
}

void OSArray::free()
{
    flushCollection();

    if (array) {
        kfree((vm_offset_t)array, sizeof(OSObject *) * capacity);
        ACCUMSIZE( -(sizeof(OSObject *) * capacity) );
    }

    super::free();
}


unsigned int OSArray::getCount() const { return count; }
unsigned int OSArray::getCapacity() const { return capacity; }
unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; }
unsigned int OSArray::setCapacityIncrement(unsigned int increment)
{
    return capacityIncrement = increment;
}

unsigned int OSArray::ensureCapacity(unsigned int newCapacity)
{
    OSObject **newArray;
    int oldSize, newSize;

    if (!capacityIncrement || newCapacity <= capacity)
        return capacity;

    // round up
    newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
                * capacityIncrement;
    newSize = sizeof(OSObject *) * newCapacity;

    newArray = (OSObject **) kalloc(newSize);
    if (newArray) {
        oldSize = sizeof(OSObject *) * capacity;

        ACCUMSIZE(newSize - oldSize);

        bcopy(array, newArray, oldSize);
        bzero(&newArray[capacity], newSize - oldSize);
        kfree((vm_offset_t)array, oldSize);
        array = newArray;
        capacity = newCapacity;
    }

    return capacity;
}

void OSArray::flushCollection()
{
    unsigned int i;

    haveUpdated();
    for (i = 0; i < count; i++)
        array[i]->release();
    count = 0;
}

bool OSArray::setObject(OSObject *anObject)
{
    return setObject(count, anObject);
}

bool OSArray::setObject(unsigned int index, OSObject *anObject)
{
    unsigned int i;
    unsigned int newCount = count + 1;

    if ((index > count) || !anObject)
        return false;

    // do we need more space?
    if (newCount > capacity && newCount > ensureCapacity(newCount))
        return false;

    haveUpdated();
    if (index != count) {
        for (i = count; i > index; i--)
            array[i] = array[i-1];
    }
    array[index] = anObject;
    anObject->retain();
    count++;

    return true;
}

bool OSArray::merge(const OSArray * otherArray)
{
    unsigned int otherCount = otherArray->getCount();
    unsigned int newCount = count + otherCount;

    if (!otherCount)
        return true;

    // do we need more space?
    if (newCount > capacity && newCount > ensureCapacity(newCount))
        return false;

    haveUpdated();
    for (unsigned int i = 0; i < otherCount; i++) {
        OSObject *newObject = otherArray->getObject(i);

        array[count++] = newObject;
        newObject->retain();
    }

    return true;
}

void OSArray::replaceObject(unsigned int index, OSObject *anObject)

{
    OSObject *oldObject;

    if ((index >= count) || !anObject)
        return;

    haveUpdated();
    oldObject = array[index];
    array[index] = anObject;
    anObject->retain();

    oldObject->release();
}

void OSArray::removeObject(unsigned int index)
{
    unsigned int i;
    OSObject *oldObject;

    if (index >= count)
        return;

    haveUpdated();
    oldObject = array[index];

    count--;
    for (i = index; i < count; i++)
        array[i] = array[i+1];

    oldObject->release();
}

bool OSArray::isEqualTo(OSArray *anArray) const
{
    unsigned int i;
    
    if ( this == anArray )
        return true;
    
    if ( count != anArray->getCount() )
        return false;

    for ( i = 0; i < count; i++ ) {
        if ( !array[i]->isEqualTo(anArray->getObject(i)) )
            return false;
    }

    return true;
}

bool OSArray::isEqualTo(const OSObject *anObject) const
{
    OSArray *otherArray;

    otherArray = OSDynamicCast(OSArray, (OSObject *)anObject);
    if ( otherArray )
        return isEqualTo(otherArray);
    else
        return false;
}

OSObject *OSArray::getObject(unsigned int index) const
{
    if (index >= count)
        return 0;
    else
        return array[index];
}

OSObject *OSArray::lastObject() const
{
    if (count == 0)
        return 0;
    else
        return array[count - 1];
}

unsigned int OSArray::getNextIndexOfObject(OSObject * anObject,
                                            unsigned int index) const
{
    while ((index < count) && (array[index] != anObject))
        {}
    if (index >= count)
        index = (unsigned int)-1;
    return index;
}

unsigned int OSArray::iteratorSize() const
{
    return sizeof(unsigned int);
}

bool OSArray::initIterator(void *inIterator) const
{
    unsigned int *iteratorP = (unsigned int *) inIterator;

    *iteratorP = 0;
    return true;
}

bool OSArray::getNextObjectForIterator(void *inIterator, OSObject **ret) const
{
    unsigned int *iteratorP = (unsigned int *) inIterator;
    unsigned int index = (*iteratorP)++;

    if (index < count) {
        *ret = array[index];
        return true;
    }
    else {
        *ret = 0;
        return false;
    }
}

bool OSArray::serialize(OSSerialize *s) const
{
    if (s->previouslySerialized(this)) return true;
    
    if (!s->addXMLStartTag(this, "array")) return false;

    for (unsigned i = 0; i < count; i++) { 
        if (!array[i]->serialize(s)) return false;
    }

    return s->addXMLEndTag("array");
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.