#ifndef _H_CSSMLIST
#define _H_CSSMLIST
#include <security_utilities/utilities.h>
#include <security_cdsa_utilities/cssmalloc.h>
#include <security_cdsa_utilities/cssmwalkers.h>
namespace Security {
class CssmList;
class TypedList;
class ListElement : public PodWrapper<ListElement, CSSM_LIST_ELEMENT> {
public:
CSSM_LIST_ELEMENT_TYPE type() const { return ElementType; }
bool is(CSSM_LIST_ELEMENT_TYPE t) const { return type() == t; }
ListElement * &next() { return ListElement::overlayVar(NextElement); }
ListElement *next() const { return ListElement::overlay(NextElement); }
ListElement *last();
explicit ListElement(const CssmData &data);
explicit ListElement(Allocator &alloc, const CssmData &data);
explicit ListElement(Allocator &alloc, const std::string &stringData);
CssmData &data();
string toString() const { return data().toString(); }
const CssmData &data() const;
ListElement &operator = (const CssmData &data);
operator CssmData &() { return data(); }
operator std::string () const { return toString(); }
bool operator == (const CssmData &other) const { return data() == other; }
bool operator != (const CssmData &other) const { return data() != other; }
template <class T>
void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA)
{ data().extract(destination, error); }
explicit ListElement(const CssmList &list);
CssmList &list();
const CssmList &list() const;
TypedList &typedList();
const TypedList &typedList() const;
ListElement &operator = (const CssmList &list);
operator CssmList &() { return list(); }
operator TypedList &();
explicit ListElement(CSSM_WORDID_TYPE word);
CSSM_WORDID_TYPE word() const;
ListElement &operator = (CSSM_WORDID_TYPE word);
operator CSSM_WORDID_TYPE () const { return word(); }
public:
void *operator new (size_t size, Allocator &alloc)
{ return alloc.malloc(size); }
void clear(Allocator &alloc); };
}
inline void destroy(ListElement *elem, Allocator &alloc)
{
elem->clear(alloc);
alloc.free(elem);
}
namespace Security {
class CssmList : public PodWrapper<CssmList, CSSM_LIST> {
public:
CssmList() { ListType = CSSM_LIST_TYPE_UNKNOWN; Head = Tail = NULL; }
CssmList(const CssmList &list) { *(CssmList *)this = list; }
public:
CSSM_LIST_TYPE kind() const { return ListType; }
ListElement &operator [] (unsigned ix) const;
unsigned int length() const;
ListElement * &first() { return ListElement::overlayVar(Head); }
ListElement *first() const { return ListElement::overlay(Head); }
ListElement *last() const { return ListElement::overlay(Tail); }
bool empty() const { return first() == NULL; }
CssmList &append(ListElement *elem);
CssmList &insert(ListElement *elem, ListElement *before);
CssmList &remove(ListElement *elem);
CssmList &operator += (ListElement *elem) { return append(elem); }
CssmList &operator -= (ListElement *elem) { return remove(elem); }
void snip();
public:
void clear(Allocator &alloc); };
}
inline void destroy(CssmList *list, Allocator &alloc)
{
list->clear(alloc);
alloc.free(list);
}
namespace Security
{
class TypedList : public CssmList {
public:
explicit TypedList(const CSSM_LIST &list) { *(CSSM_LIST *)this = list; }
TypedList(Allocator &alloc, CSSM_WORDID_TYPE type);
TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1);
TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
ListElement *elem2);
TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
ListElement *elem2, ListElement *elem3);
TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
ListElement *elem2, ListElement *elem3, ListElement *elem4);
bool isProper() const; void checkProper(CSSM_RETURN error = CSSM_ERRCODE_INVALID_SAMPLE_VALUE) const;
static TypedList &overlay(CSSM_LIST &list)
{ return static_cast<TypedList &>(list); }
static const TypedList &overlay(const CSSM_LIST &list)
{ return static_cast<const TypedList &>(list); }
CSSM_WORDID_TYPE type() const
{ assert(isProper()); return first()->word(); }
};
inline ListElement::operator TypedList &()
{ return TypedList::overlay(operator CssmList &()); }
namespace DataWalkers {
template <class Action>
ListElement *walk(Action &operate, ListElement * &elem)
{
operate(elem);
switch (elem->type()) {
case CSSM_LIST_ELEMENT_DATUM:
walk(operate, elem->data());
break;
case CSSM_LIST_ELEMENT_SUBLIST:
walk(operate, elem->list());
break;
case CSSM_LIST_ELEMENT_WORDID:
break;
default:
secdebug("walkers", "invalid list element type (%ux)", (unsigned)elem->type());
break;
}
if (elem->next())
walk(operate, elem->next());
return elem;
}
template <class Action>
ListElement *walk(Action &operate, CSSM_LIST_ELEMENT * &elem)
{ return walk(operate, ListElement::overlayVar(elem)); }
template <class Action>
void enumerate(Action &operate, CssmList &list)
{
if (!list.empty()) {
walk(operate, list.first());
if (operate.needsRelinking)
list.Tail = list.first()->last(); }
}
template <class Action>
CssmList *walk(Action &operate, CssmList * &list)
{
operate(list);
enumerate(operate, *list);
return list;
}
template <class Action>
void walk(Action &operate, CssmList &list)
{
operate(list);
enumerate(operate, list);
}
template <class Action>
void walk(Action &operate, CSSM_LIST &list)
{ walk(operate, CssmList::overlay(list)); }
template <class Action>
CSSM_LIST *walk(Action &operate, CSSM_LIST * &list)
{ return walk(operate, CssmList::overlayVar(list)); }
template <class Action>
TypedList *walk(Action &operate, TypedList * &list)
{ return static_cast<TypedList *>(walk(operate, reinterpret_cast<CssmList * &>(list))); }
template <class Action>
void walk(Action &operate, TypedList &list)
{ walk(operate, static_cast<CssmList &>(list)); }
} }
#endif //_H_CSSMLIST