/* * 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); }