X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp diff --git a/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp new file mode 100644 index 00000000..911cf2c6 --- /dev/null +++ b/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2011 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// cssmlist - CSSM_LIST operational utilities +// +#include +#include + + +// +// Managing list elements +// +ListElement *ListElement::last() +{ + for (ListElement *p = this; ; p = p->next()) + if (p->next() == NULL) + return p; + // not reached +} + + +ListElement::ListElement(CSSM_WORDID_TYPE word) +{ + ElementType = CSSM_LIST_ELEMENT_WORDID; + WordID = word; +} + +ListElement::ListElement(const CssmData &data) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = data; +} + +ListElement::ListElement(Allocator &alloc, const CssmData &data) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = CssmAutoData(alloc, data).release(); +} + +ListElement::ListElement(Allocator &alloc, const string &s) +{ + ElementType = CSSM_LIST_ELEMENT_DATUM; + WordID = 0; + Element.Word = CssmAutoData(alloc, s.data(), s.size()).release(); +} + +ListElement::ListElement(const CssmList &list) +{ + ElementType = CSSM_LIST_ELEMENT_SUBLIST; + WordID = 0; + Element.Sublist = list; +} + + +CssmData &ListElement::data() +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + return CssmData::overlay(Element.Word); +} + +const CssmData &ListElement::data() const +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + return CssmData::overlay(Element.Word); +} + +ListElement &ListElement::operator = (const CssmData &data) +{ + assert(type() == CSSM_LIST_ELEMENT_DATUM); + Element.Word = data; + return *this; +} + + +CssmList &ListElement::list() +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + return CssmList::overlay(Element.Sublist); +} + +const CssmList &ListElement::list() const +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + return CssmList::overlay(Element.Sublist); +} + +TypedList &ListElement::typedList() +{ + return static_cast(list()); +} + +const TypedList &ListElement::typedList() const +{ + return static_cast(list()); +} + +ListElement &ListElement::operator = (const CssmList &list) +{ + assert(type() == CSSM_LIST_ELEMENT_SUBLIST); + Element.Sublist = list; + return *this; +} + + +CSSM_WORDID_TYPE ListElement::word() const +{ + assert(type() == CSSM_LIST_ELEMENT_WORDID); + return WordID; +} + +ListElement &ListElement::operator = (CSSM_WORDID_TYPE word) +{ + assert(type() == CSSM_LIST_ELEMENT_WORDID); + WordID = word; + return *this; +} + + +// +// List operations +// +ListElement &CssmList::operator [] (unsigned ix) const +{ + for (ListElement *elem = first(); elem; elem = elem->next(), ix--) { + if (ix == 0) + return *elem; + } + throw 999; //@@@ +} + +unsigned int CssmList::length() const +{ + unsigned int len = 0; + for (ListElement *elem = first(); elem; elem = elem->next()) + len++; + return len; +} + +CssmList &CssmList::append(ListElement *elem) +{ + if (Tail == NULL) { // first element + Head = Tail = elem; + } else { + Tail->NextElement = elem; + Tail = elem; + } + elem->NextElement = NULL; + return *this; +} + +CssmList &CssmList::insert(ListElement *elem, ListElement *before) +{ + // null before -> append + if (before == NULL) + return append(elem); + + // we have a real position + assert(!empty()); + if (Head == before) { // before first element + elem->NextElement = before; + Head = elem; + } else { // before is not first + for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement) { + if (p->NextElement == before) { + elem->NextElement = before; + p->NextElement = elem; + return *this; + } + } + // end of list, before not in list + throw 999; //@@@ + } + return *this; +} + +CssmList &CssmList::remove(ListElement *elem) +{ + assert(elem); + if (elem == Head) { // remove first element + Head = Head->NextElement; + } else { // subsequent element + for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement) + if (p->NextElement == elem) { + p->NextElement = elem->NextElement; + if (elem->NextElement == NULL) // removing last element + Tail = p; + return *this; + } + // end of list, elem not found + throw 999; //@@@ + } + return *this; +} + +void CssmList::snip() +{ + assert(Head); // can't be empty + if (Head == Tail) { // single element, empty when snipped + Head = Tail = NULL; + } else { // more than one, bypass first + Head = first()->next(); + } +} + + +// +// Deep-destruction of CssmLists and ListElements. +// The underlying assumption is that all components were allocated from a single +// Allocator in canonical chunks. +// +void ListElement::clear(Allocator &alloc) +{ + switch (type()) { + case CSSM_LIST_ELEMENT_WORDID: + break; // no substructure + case CSSM_LIST_ELEMENT_DATUM: + alloc.free(data().data()); + break; + case CSSM_LIST_ELEMENT_SUBLIST: + list().clear(alloc); + break; + default: + assert(false); + } +} + +void CssmList::clear(Allocator &alloc) +{ + ListElement *elem = first(); + while (elem) { + ListElement *next = elem->next(); + destroy(elem, alloc); + elem = next; + } +} + + +// +// Building TypedLists +// +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type) +{ + append(new(alloc) ListElement(type)); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1) +{ + append(new(alloc) ListElement(type)); + append(elem1); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); + append(elem3); +} + +TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3, ListElement *elem4) +{ + append(new(alloc) ListElement(type)); + append(elem1); + append(elem2); + append(elem3); + append(elem4); +} + + +// +// Verify that a TypedList is "proper", i.e. has a first element of WORDID form +// +bool TypedList::isProper() const +{ + return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID; +} + +void TypedList::checkProper(CSSM_RETURN error) const +{ + if (!isProper()) + CssmError::throwMe(error); +}