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.cpp 21// 22 23#include "MetaAttribute.h" 24#include "MetaRecord.h" 25 26MetaAttribute::~MetaAttribute() 27{ 28} 29 30// Construct an instance of an appropriate subclass of MetaAttribute 31// based on the given format. 32 33MetaAttribute * 34MetaAttribute::create(Format format, uint32 attributeIndex, 35 uint32 attributeId) 36{ 37 switch (format) 38 { 39 case CSSM_DB_ATTRIBUTE_FORMAT_STRING: 40 return new TypedMetaAttribute<StringValue>(format, attributeIndex, attributeId); 41 42 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: 43 return new TypedMetaAttribute<SInt32Value>(format, attributeIndex, attributeId); 44 45 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: 46 return new TypedMetaAttribute<UInt32Value>(format, attributeIndex, attributeId); 47 48 case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: 49 return new TypedMetaAttribute<BigNumValue>(format, attributeIndex, attributeId); 50 51 case CSSM_DB_ATTRIBUTE_FORMAT_REAL: 52 return new TypedMetaAttribute<DoubleValue>(format, attributeIndex, attributeId); 53 54 case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: 55 return new TypedMetaAttribute<TimeDateValue>(format, attributeIndex, attributeId); 56 57 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: 58 return new TypedMetaAttribute<BlobValue>(format, attributeIndex, attributeId); 59 60 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: 61 return new TypedMetaAttribute<MultiUInt32Value>(format, attributeIndex, attributeId); 62 63 case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: 64 default: 65 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT); 66 } 67} 68 69void 70MetaAttribute::packNumberOfValues(WriteSection &ws, uint32 numValues, uint32 &valueOffset) const 71{ 72 uint32 offset = MetaRecord::OffsetAttributeOffsets + mAttributeIndex * AtomSize; 73 74 if (numValues == 0) { 75 // a zero offset means the attribute has no values 76 ws.put(offset, 0); 77 } 78 else if (numValues == 1) { 79 // setting the low bit of the offset means that there is exactly one value 80 ws.put(offset, valueOffset | 1); 81 } 82 else { 83 // write the offset, then write the number of values at that position 84 ws.put(offset, valueOffset); 85 valueOffset = ws.put(valueOffset, numValues); 86 } 87} 88 89void 90MetaAttribute::unpackNumberOfValues(const ReadSection &rs, uint32 &numValues, 91 uint32 &valueOffset) const 92{ 93 uint32 offset = MetaRecord::OffsetAttributeOffsets + mAttributeIndex * AtomSize; 94 valueOffset = rs[offset]; 95 96 if (valueOffset == 0) 97 // a zero offset means no values 98 numValues = 0; 99 else if (valueOffset & 1) { 100 // setting the LSB means exactly one value 101 valueOffset ^= 1; 102 numValues = 1; 103 } 104 else { 105 // otherwise, the number of values is at the offset, and the values follow 106 numValues = rs[valueOffset]; 107 valueOffset += AtomSize; 108 } 109} 110 111void 112MetaAttribute::packAttribute(WriteSection &ws, uint32 &valueOffset, uint32 numValues, 113 const CSSM_DATA *values) const 114{ 115 packNumberOfValues(ws, numValues, valueOffset); 116 for (uint32 i = 0; i < numValues; i++) 117 packValue(ws, valueOffset, values[i]); 118} 119 120void 121MetaAttribute::unpackAttribute(const ReadSection &rs, Allocator &allocator, 122 uint32 &numValues, CSSM_DATA *&values) const 123{ 124 uint32 valueOffset; 125 unpackNumberOfValues(rs, numValues, valueOffset); 126 127 // Rough check for number of values; will be more like 10 or 20 128 if (numValues > 1024) 129 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 130 131 values = reinterpret_cast<CSSM_DATA *>(allocator.malloc(numValues * sizeof(CSSM_DATA))); 132 133 for (uint32 i = 0; i < numValues; i++) 134 unpackValue(rs, valueOffset, values[i], allocator); 135} 136 137uint32 138MetaAttribute::getNumberOfValues(const ReadSection &rs) const 139{ 140 uint32 numValues, valueOffset; 141 unpackNumberOfValues(rs, numValues, valueOffset); 142 return numValues; 143} 144 145void 146MetaAttribute::copyValueBytes(uint32 valueIndex, const ReadSection &rs, WriteSection &ws, 147 uint32 &writeOffset) const 148{ 149 uint32 numValues, valueOffset; 150 unpackNumberOfValues(rs, numValues, valueOffset); 151 152 // skip bytes before the desired value 153 for (uint32 i = 0; i < valueIndex; i++) 154 skipValue(rs, valueOffset); 155 156 // copy the value bytes into the write section 157 copyValue(rs, valueOffset, ws, writeOffset); 158} 159