1/*
2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// MetaAttribute.h
21//
22
23#ifndef _H_APPLEDL_METAATTRIBUTE
24#define _H_APPLEDL_METAATTRIBUTE
25
26#include "DbValue.h"
27#include <memory>
28
29namespace Security
30{
31
32// A base class for all meta attributes.
33
34class MetaAttribute
35{
36public:
37	typedef CSSM_DB_ATTRIBUTE_FORMAT Format;
38
39	virtual ~MetaAttribute();
40
41	// construct an appropriate subclass of MetaAttribute
42	static MetaAttribute *create(Format format, uint32 attributeIndex,
43		uint32 attributeId);
44
45	Format attributeFormat() const { return mFormat; }
46	uint32 attributeIndex() const { return mAttributeIndex; }
47	uint32 attributeId() const { return mAttributeId; }
48
49	void packAttribute(WriteSection &ws, uint32 &valueOffset,
50		uint32 numValues, const CSSM_DATA *values) const;
51	void unpackAttribute(const ReadSection &rs, Allocator &allocator,
52		uint32 &numValues, CSSM_DATA *&values) const;
53
54	uint32 getNumberOfValues(const ReadSection &rs) const;
55	void copyValueBytes(uint32 valueIndex, const ReadSection &rs, WriteSection &ws,
56		uint32 &writeOffset) const;
57
58	// interface required of all subclasses, implemented with templates below
59	virtual DbValue *createValue(const CSSM_DATA &data) const = 0;
60	virtual DbValue *createValue(const ReadSection &rs, uint32 &offset) const = 0;
61	virtual void packValue(WriteSection &ws, uint32 &offset, const CSSM_DATA &data) const = 0;
62	virtual void unpackValue(const ReadSection &rs, uint32 &offset, CSSM_DATA &data,
63		Allocator &allocator) const = 0;
64	virtual void skipValue(const ReadSection &rs, uint32 &offset) const = 0;
65	virtual void copyValue(const ReadSection &rs, uint32 &readOffset, WriteSection &ws,
66		uint32 &writeOffset) const = 0;
67	virtual bool evaluate(const DbValue *value, const ReadSection &rs, CSSM_DB_OPERATOR op) const = 0;
68	virtual bool evaluate(const DbValue *value1, const DbValue *value2, CSSM_DB_OPERATOR op) const = 0;
69	virtual uint32 parse(const CssmData &inData, CSSM_DATA_PTR &outValues) const = 0;
70
71protected:
72	MetaAttribute(Format format, uint32 attributeIndex, uint32 attributeId)
73	: mFormat(format), mAttributeIndex(attributeIndex), mAttributeId(attributeId) {}
74
75	void packNumberOfValues(WriteSection &ws, uint32 numValues, uint32 &valueOffset) const;
76	void unpackNumberOfValues(const ReadSection &rs, uint32 &numValues, uint32 &valueOffset) const;
77
78	Format mFormat;
79	uint32 mAttributeIndex;
80	uint32 mAttributeId;
81};
82
83// Template used to describe particular subclasses of MetaAttribute
84
85template <class T>
86class TypedMetaAttribute : public MetaAttribute
87{
88public:
89	TypedMetaAttribute(Format format, uint32 attributeIndex, uint32 attributeId)
90	: MetaAttribute(format, attributeIndex, attributeId) {}
91
92	DbValue *createValue(const CSSM_DATA &data) const
93	{
94		return new T(data);
95	}
96
97	DbValue *createValue(const ReadSection &rs, uint32 &offset) const
98	{
99		return new T(rs, offset);
100	}
101
102	void packValue(WriteSection &ws, uint32 &offset, const CSSM_DATA &data) const
103	{
104		T value(data);
105		value.pack(ws, offset);
106	}
107
108	void unpackValue(const ReadSection &rs, uint32 &offset, CSSM_DATA &data, Allocator &allocator) const
109	{
110		T value(rs, offset);
111		data.Length = value.size();
112
113		if (data.Length != 0)
114		{
115			data.Data = reinterpret_cast<uint8 *>(allocator.malloc(data.Length));
116			memcpy(data.Data, value.bytes(), data.Length);
117		}
118		else
119		{
120			data.Data = NULL;
121		}
122	}
123
124	void skipValue(const ReadSection &rs, uint32 &offset) const
125	{
126		T value(rs, offset);
127	}
128
129	void copyValue(const ReadSection &rs, uint32 &readOffset, WriteSection &ws, uint32 &writeOffset) const
130	{
131		T value(rs, readOffset);
132		value.pack(ws, writeOffset);
133	}
134
135	bool evaluate(const DbValue *value, const ReadSection &rs, CSSM_DB_OPERATOR op) const
136	{
137		uint32 offset, numValues;
138		unpackNumberOfValues(rs, numValues, offset);
139
140		/* If any of the values for this attribute match we have a
141		   match.   This is the same behaviour that indexes have. */
142		for (uint32 ix = 0; ix < numValues; ++ix)
143			if (dynamic_cast<const T *>(value)->evaluate(T(rs, offset), op))
144				return true;
145
146		return false;
147	}
148
149	bool evaluate(const DbValue *value1, const DbValue *value2, CSSM_DB_OPERATOR op) const
150	{
151		return (dynamic_cast<const T *>(value1))->evaluate(*dynamic_cast<const T *>(value2), op);
152	}
153
154    uint32 parse(const CssmData &inData, CSSM_DATA_PTR &outValues) const
155	{
156		return 0;
157	}
158};
159
160} // end namespace Security
161
162#endif //  _H_APPLEDL_METAATTRIBUTE
163