2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
37 UInt32Value::UInt32Value(const ReadSection
&rs
, uint32
&offset
)
38 : BasicValue
<uint32
>(rs
.at(offset
))
43 UInt32Value::UInt32Value(const CSSM_DATA
&data
)
48 mValue
= *reinterpret_cast<uint8
*>(data
.Data
);
51 mValue
= *reinterpret_cast<uint16
*>(data
.Data
);
54 mValue
= *reinterpret_cast<uint32
*>(data
.Data
);
57 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
61 UInt32Value::~UInt32Value()
66 UInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
68 offset
= ws
.put(offset
, mValue
);
75 SInt32Value::SInt32Value(const ReadSection
&rs
, uint32
&offset
)
76 : BasicValue
<sint32
>(static_cast<sint32
>(rs
.at(offset
)))
81 SInt32Value::SInt32Value(const CSSM_DATA
&data
)
86 mValue
= *reinterpret_cast<sint8
*>(data
.Data
);
89 mValue
= *reinterpret_cast<sint16
*>(data
.Data
);
92 mValue
= *reinterpret_cast<sint32
*>(data
.Data
);
95 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
99 SInt32Value::~SInt32Value()
104 SInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
106 offset
= ws
.put(offset
, static_cast<uint32
>(mValue
));
113 DoubleValue::DoubleValue(const ReadSection
&rs
, uint32
&offset
)
115 Range
r(offset
, size());
116 mValue
= *reinterpret_cast<const double *>(rs
.range(r
));
120 DoubleValue::DoubleValue(const CSSM_DATA
&data
)
125 mValue
= *reinterpret_cast<float *>(data
.Data
);
128 mValue
= *reinterpret_cast<double *>(data
.Data
);
131 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
135 DoubleValue::~DoubleValue()
140 DoubleValue::pack(WriteSection
&ws
, uint32
&offset
) const
142 offset
= ws
.put(offset
, size(), bytes());
149 BlobValue::BlobValue(const ReadSection
&rs
, uint32
&offset
)
151 Length
= rs
.at(offset
);
152 Data
= const_cast<uint8
*>(rs
.range(Range(offset
+ AtomSize
, Length
)));
153 offset
= ReadSection::align(offset
+ Length
+ AtomSize
);
156 BlobValue::BlobValue(const CSSM_DATA
&data
)
157 : CssmData(CssmData::overlay(data
))
161 BlobValue::~BlobValue()
166 BlobValue::pack(WriteSection
&ws
, uint32
&offset
) const
168 offset
= ws
.put(offset
, Length
);
169 offset
= ws
.put(offset
, Length
, Data
);
172 BlobValue::Comparator::~Comparator()
177 BlobValue::Comparator::operator () (const uint8
*ptr1
, const uint8
*ptr2
, uint32 length
)
179 return memcmp(ptr1
, ptr2
, length
);
183 BlobValue::evaluate(const BlobValue
&other
, CSSM_DB_OPERATOR op
) const
185 return evaluate(*this, other
, op
, Comparator());
189 BlobValue::evaluate(const CssmData
&inData1
, const CssmData
&inData2
, CSSM_DB_OPERATOR op
,
192 uint32 length1
= inData1
.Length
, length2
= inData2
.Length
;
193 const uint8
*data1
= inData1
.Data
;
194 const uint8
*data2
= inData2
.Data
;
198 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
199 if (length1
> length2
)
204 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
205 if (length1
> length2
)
207 data2
+= (length2
- length1
);
213 if (length1
!= length2
)
217 return compare(data1
, data2
, length1
) == 0;
219 case CSSM_DB_NOT_EQUAL
:
220 if (length1
!= length2
)
224 return compare(data1
, data2
, length1
) != 0;
226 case CSSM_DB_LESS_THAN
:
227 case CSSM_DB_GREATER_THAN
:
229 uint32 length
= min(length1
, length2
);
230 int result
= (length
== 0) ? 0 : compare(data1
, data2
, length
);
232 if (result
< 0 || (result
== 0 && length1
< length2
))
233 return op
== CSSM_DB_LESS_THAN
;
234 else if (result
> 0 || (result
== 0 && length1
> length2
))
235 return op
== CSSM_DB_GREATER_THAN
;
239 case CSSM_DB_CONTAINS
:
240 if (length1
> length2
)
244 // Both buffers are at least 1 byte long.
245 for (const uint8
*data
= data2
; data
+ length1
<= data2
+ length2
; data
++)
246 if (compare(data1
, data
, length1
) == 0)
251 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);
261 TimeDateValue::TimeDateValue(const ReadSection
&rs
, uint32
&offset
)
263 Length
= kTimeDateSize
;
264 Data
= const_cast<uint8
*>(rs
.range(Range(offset
, Length
)));
265 offset
= ReadSection::align(offset
+ Length
);
268 TimeDateValue::TimeDateValue(const CSSM_DATA
&data
)
271 if (Length
!= kTimeDateSize
|| !isValidDate())
272 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
275 TimeDateValue::~TimeDateValue()
280 TimeDateValue::pack(WriteSection
&ws
, uint32
&offset
) const
282 offset
= ws
.put(offset
, Length
, Data
);
286 TimeDateValue::isValidDate() const
288 if (Length
!= kTimeDateSize
|| Data
[kTimeDateSize
- 1] != 0 ||
289 Data
[kTimeDateSize
- 2] != 'Z')
292 for (uint32 i
= 0; i
< kTimeDateSize
- 2; i
++)
293 if (!isdigit(Data
[i
]))
296 uint32 month
= rangeValue(4, 2);
297 if (month
< 1 || month
> 12)
300 uint32 day
= rangeValue(6, 2);
301 if (day
< 1 || day
> 31)
304 uint32 hour
= rangeValue(8, 2);
305 if (hour
< 0 || hour
> 23)
308 uint32 minute
= rangeValue(10, 2);
309 if (minute
< 0 || minute
> 59)
312 uint32 second
= rangeValue(12, 2);
313 if (second
< 0 || second
> 59)
320 TimeDateValue::rangeValue(uint32 start
, uint32 length
) const
323 for (uint32 i
= 0; i
< length
; i
++)
324 value
= value
* 10 + Data
[start
+ i
] - '0';
332 StringValue::StringValue(const ReadSection
&rs
, uint32
&offset
)
333 : BlobValue(rs
, offset
)
337 StringValue::StringValue(const CSSM_DATA
&data
)
342 StringValue::~StringValue()
347 StringValue::Comparator::operator () (const uint8
*ptr1
, const uint8
*ptr2
, uint32 length
)
349 return strncmp(reinterpret_cast<const char *>(ptr1
),
350 reinterpret_cast<const char *>(ptr2
), length
);
354 StringValue::evaluate(const StringValue
&other
, CSSM_DB_OPERATOR op
) const
356 return BlobValue::evaluate(*this, other
, op
, StringValue::Comparator());
363 BigNumValue::BigNumValue(const ReadSection
&rs
, uint32
&offset
)
364 : BlobValue(rs
, offset
)
368 BigNumValue::BigNumValue(const CSSM_DATA
&data
)
371 // remove trailing zero bytes
372 while (Length
> 1 && Data
[Length
- 1] == 0)
375 // if the number is zero (positive or negative), make the length zero
376 if (Length
== 1 && (Data
[0] & ~kSignBit
) == 0)
380 BigNumValue::~BigNumValue()
384 // Walk the contents of two equal-sized bignums, moving backward
385 // from the high-order bytes, and return the comparison result
389 BigNumValue::compare(const uint8
*a
, const uint8
*b
, int length
)
391 for (int diff
, i
= length
- 1; i
>= 1; i
--)
392 if (diff
= a
[i
] - b
[i
])
395 // for the last (i.e. first) byte, mask out the sign bit
396 return (a
[0] & ~kSignBit
) - (b
[0] & ~kSignBit
);
399 // Compare two bignums, assuming they are in canonical form (i.e.,
400 // no bytes containing trailing zeros.
403 BigNumValue::evaluate(const BigNumValue
&other
, CSSM_DB_OPERATOR op
) const
405 uint32 length1
= Length
, length2
= other
.Length
;
406 uint8 sign1
= length1
? (Data
[0] & kSignBit
) : 0;
407 uint8 sign2
= length2
? (other
.Data
[0] & kSignBit
) : 0;
412 case CSSM_DB_NOT_EQUAL
:
413 return BlobValue::evaluate(other
, op
);
415 case CSSM_DB_LESS_THAN
:
417 // different signs: return true iff left value is the negative one
419 else if (length1
!= length2
)
420 // in canonical form, shorter numbers have smaller absolute value
421 return sign1
? (length1
> length2
) : (length1
< length2
);
423 // same length, same sign...
424 int c
= compare(Data
, other
.Data
, length1
);
425 return sign1
? (c
> 0) : (c
< 0);
429 case CSSM_DB_GREATER_THAN
:
432 else if (length1
!= length2
)
433 return sign1
? (length1
< length2
) : (length1
> length2
);
435 int c
= compare(Data
, other
.Data
, length1
);
436 return sign1
? (c
< 0) : (c
> 0);
440 case CSSM_DB_CONTAINS
:
441 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
442 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
444 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);
452 MultiUInt32Value::MultiUInt32Value(const ReadSection
&rs
, uint32
&offset
)
454 // this is relatively expensive, since it copies the data from the
455 // read section to get the endianness correct
457 mNumValues
= rs
.at(offset
);
458 mValues
= new uint32
[mNumValues
];
460 for (uint32 i
= 0; i
< mNumValues
; i
++)
461 mValues
[i
] = rs
.at(offset
+ (i
+ 1) * AtomSize
);
463 offset
= ReadSection::align(offset
+ (mNumValues
+ 1) * AtomSize
);
467 MultiUInt32Value::MultiUInt32Value(const CSSM_DATA
&data
)
469 if (data
.Length
& (sizeof(uint32
) - 1))
470 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
472 mNumValues
= data
.Length
/ sizeof(uint32
);
473 mValues
= reinterpret_cast<uint32
*>(data
.Data
);
477 MultiUInt32Value::~MultiUInt32Value()
484 MultiUInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
486 offset
= ws
.put(offset
, mNumValues
);
487 for (uint32 i
= 0; i
< mNumValues
; i
++)
488 offset
= ws
.put(offset
, mValues
[i
]);
492 uint32cmp(const uint32
*a
, const uint32
*b
, uint32 length
)
494 return memcmp(a
, b
, length
* sizeof(uint32
));
498 MultiUInt32Value::evaluate(const MultiUInt32Value
&other
, CSSM_DB_OPERATOR op
) const
500 uint32 length1
= mNumValues
, length2
= other
.mNumValues
;
501 const uint32
*values1
= mValues
;
502 const uint32
*values2
= other
.mValues
;
507 if (length1
== length2
)
508 return uint32cmp(values1
, values2
, length1
) == 0;
511 case CSSM_DB_NOT_EQUAL
:
512 if (length1
!= length2
|| uint32cmp(values1
, values2
, length1
))
516 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
517 if (length1
<= length2
)
518 return uint32cmp(values1
, values2
, length1
) == 0;
521 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
522 if (length1
<= length2
)
523 return uint32cmp(values1
, values2
+ (length2
- length1
), length1
) == 0;
526 case CSSM_DB_CONTAINS
:
527 if (length1
<= length2
) {
532 for (const uint32
*values
= values2
; values
+ length1
< values2
+ length2
; values
++)
533 if (uint32cmp(values1
, values
, length1
) == 0)
538 case CSSM_DB_LESS_THAN
:
539 // this is not required by the spec, but is required to sort indexes over
540 // multi uint32 keys...
541 if (length1
< length2
)
543 else if (length1
== length2
)
544 return uint32cmp(values1
, values2
, length1
) < 0;
548 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);