]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / 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 (file)
index 0000000..911cf2c
--- /dev/null
@@ -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 <security_cdsa_utilities/cssmlist.h>
+#include <security_cdsa_utilities/cssmdata.h>
+
+
+//
+// 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<TypedList &>(list());
+}
+
+const TypedList &ListElement::typedList() const
+{
+       return static_cast<const TypedList &>(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);
+}