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.
38 UInt32Value::UInt32Value(const ReadSection
&rs
, uint32
&offset
)
39 : BasicValue
<uint32
>(rs
.at(offset
))
44 UInt32Value::UInt32Value(const CSSM_DATA
&data
)
49 mValue
= *reinterpret_cast<uint8
*>(data
.Data
);
52 mValue
= *reinterpret_cast<uint16
*>(data
.Data
);
55 mValue
= *reinterpret_cast<uint32
*>(data
.Data
);
58 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
62 UInt32Value::~UInt32Value()
67 UInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
69 offset
= ws
.put(offset
, mValue
);
76 SInt32Value::SInt32Value(const ReadSection
&rs
, uint32
&offset
)
77 : BasicValue
<sint32
>(static_cast<sint32
>(rs
.at(offset
)))
82 SInt32Value::SInt32Value(const CSSM_DATA
&data
)
87 mValue
= *reinterpret_cast<sint8
*>(data
.Data
);
90 mValue
= *reinterpret_cast<sint16
*>(data
.Data
);
93 mValue
= *reinterpret_cast<sint32
*>(data
.Data
);
96 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
100 SInt32Value::~SInt32Value()
105 SInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
107 offset
= ws
.put(offset
, static_cast<uint32
>(mValue
));
114 DoubleValue::DoubleValue(const ReadSection
&rs
, uint32
&offset
)
116 Range
r(offset
, size());
117 mValue
= *reinterpret_cast<const double *>(rs
.range(r
));
121 DoubleValue::DoubleValue(const CSSM_DATA
&data
)
126 mValue
= *reinterpret_cast<float *>(data
.Data
);
129 mValue
= *reinterpret_cast<double *>(data
.Data
);
132 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
136 DoubleValue::~DoubleValue()
141 DoubleValue::pack(WriteSection
&ws
, uint32
&offset
) const
143 offset
= ws
.put(offset
, size(), bytes());
150 BlobValue::BlobValue(const ReadSection
&rs
, uint32
&offset
)
152 Length
= rs
.at(offset
);
153 Data
= const_cast<uint8
*>(rs
.range(Range(offset
+ AtomSize
, Length
)));
154 offset
= ReadSection::align(offset
+ Length
+ AtomSize
);
157 BlobValue::BlobValue(const CSSM_DATA
&data
)
158 : CssmData(CssmData::overlay(data
))
162 BlobValue::~BlobValue()
167 BlobValue::pack(WriteSection
&ws
, uint32
&offset
) const
169 offset
= ws
.put(offset
, Length
);
170 offset
= ws
.put(offset
, Length
, Data
);
173 BlobValue::Comparator::~Comparator()
178 BlobValue::Comparator::operator () (const uint8
*ptr1
, const uint8
*ptr2
, uint32 length
)
180 return memcmp(ptr1
, ptr2
, length
);
184 BlobValue::evaluate(const BlobValue
&other
, CSSM_DB_OPERATOR op
) const
186 return evaluate(*this, other
, op
, Comparator());
190 BlobValue::evaluate(const CssmData
&inData1
, const CssmData
&inData2
, CSSM_DB_OPERATOR op
,
193 uint32 length1
= inData1
.Length
, length2
= inData2
.Length
;
194 const uint8
*data1
= inData1
.Data
;
195 const uint8
*data2
= inData2
.Data
;
199 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
200 if (length1
> length2
)
205 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
206 if (length1
> length2
)
208 data2
+= (length2
- length1
);
214 if (length1
!= length2
)
218 return compare(data1
, data2
, length1
) == 0;
220 case CSSM_DB_NOT_EQUAL
:
221 if (length1
!= length2
)
225 return compare(data1
, data2
, length1
) != 0;
227 case CSSM_DB_LESS_THAN
:
228 case CSSM_DB_GREATER_THAN
:
230 uint32 length
= min(length1
, length2
);
231 int result
= (length
== 0) ? 0 : compare(data1
, data2
, length
);
233 if (result
< 0 || (result
== 0 && length1
< length2
))
234 return op
== CSSM_DB_LESS_THAN
;
235 else if (result
> 0 || (result
== 0 && length1
> length2
))
236 return op
== CSSM_DB_GREATER_THAN
;
240 case CSSM_DB_CONTAINS
:
241 if (length1
> length2
)
245 // Both buffers are at least 1 byte long.
246 for (const uint8
*data
= data2
; data
+ length1
<= data2
+ length2
; data
++)
247 if (compare(data1
, data
, length1
) == 0)
252 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);
262 TimeDateValue::TimeDateValue(const ReadSection
&rs
, uint32
&offset
)
264 Length
= kTimeDateSize
;
265 Data
= const_cast<uint8
*>(rs
.range(Range(offset
, Length
)));
266 offset
= ReadSection::align(offset
+ Length
);
269 TimeDateValue::TimeDateValue(const CSSM_DATA
&data
)
272 if (Length
!= kTimeDateSize
|| !isValidDate())
273 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
276 TimeDateValue::~TimeDateValue()
281 TimeDateValue::pack(WriteSection
&ws
, uint32
&offset
) const
283 offset
= ws
.put(offset
, Length
, Data
);
287 TimeDateValue::isValidDate() const
289 if (Length
!= kTimeDateSize
|| Data
[kTimeDateSize
- 1] != 0 ||
290 Data
[kTimeDateSize
- 2] != 'Z')
293 for (uint32 i
= 0; i
< kTimeDateSize
- 2; i
++)
294 if (!isdigit(Data
[i
]))
297 uint32 month
= rangeValue(4, 2);
298 if (month
< 1 || month
> 12)
301 uint32 day
= rangeValue(6, 2);
302 if (day
< 1 || day
> 31)
305 uint32 hour
= rangeValue(8, 2);
306 if (hour
< 0 || hour
> 23)
309 uint32 minute
= rangeValue(10, 2);
310 if (minute
< 0 || minute
> 59)
313 uint32 second
= rangeValue(12, 2);
314 if (second
< 0 || second
> 59)
321 TimeDateValue::rangeValue(uint32 start
, uint32 length
) const
324 for (uint32 i
= 0; i
< length
; i
++)
325 value
= value
* 10 + Data
[start
+ i
] - '0';
333 StringValue::StringValue(const ReadSection
&rs
, uint32
&offset
)
334 : BlobValue(rs
, offset
)
338 StringValue::StringValue(const CSSM_DATA
&data
)
343 StringValue::~StringValue()
348 StringValue::Comparator::operator () (const uint8
*ptr1
, const uint8
*ptr2
, uint32 length
)
350 return strncmp(reinterpret_cast<const char *>(ptr1
),
351 reinterpret_cast<const char *>(ptr2
), length
);
355 StringValue::evaluate(const StringValue
&other
, CSSM_DB_OPERATOR op
) const
357 return BlobValue::evaluate(*this, other
, op
, StringValue::Comparator());
364 BigNumValue::BigNumValue(const ReadSection
&rs
, uint32
&offset
)
365 : BlobValue(rs
, offset
)
369 BigNumValue::BigNumValue(const CSSM_DATA
&data
)
372 // remove trailing zero bytes
373 while (Length
> 1 && Data
[Length
- 1] == 0)
376 // if the number is zero (positive or negative), make the length zero
377 if (Length
== 1 && (Data
[0] & ~kSignBit
) == 0)
381 BigNumValue::~BigNumValue()
385 // Walk the contents of two equal-sized bignums, moving backward
386 // from the high-order bytes, and return the comparison result
390 BigNumValue::compare(const uint8
*a
, const uint8
*b
, int length
)
392 for (int diff
, i
= length
- 1; i
>= 1; i
--)
393 if ((diff
= a
[i
] - b
[i
]))
396 // for the last (i.e. first) byte, mask out the sign bit
397 return (a
[0] & ~kSignBit
) - (b
[0] & ~kSignBit
);
400 // Compare two bignums, assuming they are in canonical form (i.e.,
401 // no bytes containing trailing zeros.
404 BigNumValue::evaluate(const BigNumValue
&other
, CSSM_DB_OPERATOR op
) const
406 uint32 length1
= Length
, length2
= other
.Length
;
407 uint8 sign1
= length1
? (Data
[0] & kSignBit
) : 0;
408 uint8 sign2
= length2
? (other
.Data
[0] & kSignBit
) : 0;
413 case CSSM_DB_NOT_EQUAL
:
414 return BlobValue::evaluate(other
, op
);
416 case CSSM_DB_LESS_THAN
:
418 // different signs: return true iff left value is the negative one
420 else if (length1
!= length2
)
421 // in canonical form, shorter numbers have smaller absolute value
422 return sign1
? (length1
> length2
) : (length1
< length2
);
424 // same length, same sign...
425 int c
= compare(Data
, other
.Data
, length1
);
426 return sign1
? (c
> 0) : (c
< 0);
430 case CSSM_DB_GREATER_THAN
:
433 else if (length1
!= length2
)
434 return sign1
? (length1
< length2
) : (length1
> length2
);
436 int c
= compare(Data
, other
.Data
, length1
);
437 return sign1
? (c
< 0) : (c
> 0);
441 case CSSM_DB_CONTAINS
:
442 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
443 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
445 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);
453 MultiUInt32Value::MultiUInt32Value(const ReadSection
&rs
, uint32
&offset
)
455 // this is relatively expensive, since it copies the data from the
456 // read section to get the endianness correct
458 mNumValues
= rs
.at(offset
);
459 mValues
= new uint32
[mNumValues
];
461 for (uint32 i
= 0; i
< mNumValues
; i
++)
462 mValues
[i
] = rs
.at(offset
+ (i
+ 1) * AtomSize
);
464 offset
= ReadSection::align(offset
+ (mNumValues
+ 1) * AtomSize
);
468 MultiUInt32Value::MultiUInt32Value(const CSSM_DATA
&data
)
470 if (data
.Length
& (sizeof(uint32
) - 1))
471 CssmError::throwMe(CSSMERR_DL_INVALID_VALUE
);
473 mNumValues
= data
.Length
/ sizeof(uint32
);
474 mValues
= reinterpret_cast<uint32
*>(data
.Data
);
478 MultiUInt32Value::~MultiUInt32Value()
485 MultiUInt32Value::pack(WriteSection
&ws
, uint32
&offset
) const
487 offset
= ws
.put(offset
, mNumValues
);
488 for (uint32 i
= 0; i
< mNumValues
; i
++)
489 offset
= ws
.put(offset
, mValues
[i
]);
493 uint32cmp(const uint32
*a
, const uint32
*b
, uint32 length
)
495 return memcmp(a
, b
, length
* sizeof(uint32
));
499 MultiUInt32Value::evaluate(const MultiUInt32Value
&other
, CSSM_DB_OPERATOR op
) const
501 uint32 length1
= mNumValues
, length2
= other
.mNumValues
;
502 const uint32
*values1
= mValues
;
503 const uint32
*values2
= other
.mValues
;
508 if (length1
== length2
)
509 return uint32cmp(values1
, values2
, length1
) == 0;
512 case CSSM_DB_NOT_EQUAL
:
513 if (length1
!= length2
|| uint32cmp(values1
, values2
, length1
))
517 case CSSM_DB_CONTAINS_INITIAL_SUBSTRING
:
518 if (length1
<= length2
)
519 return uint32cmp(values1
, values2
, length1
) == 0;
522 case CSSM_DB_CONTAINS_FINAL_SUBSTRING
:
523 if (length1
<= length2
)
524 return uint32cmp(values1
, values2
+ (length2
- length1
), length1
) == 0;
527 case CSSM_DB_CONTAINS
:
528 if (length1
<= length2
) {
533 for (const uint32
*values
= values2
; values
+ length1
< values2
+ length2
; values
++)
534 if (uint32cmp(values1
, values
, length1
) == 0)
539 case CSSM_DB_LESS_THAN
:
540 // this is not required by the spec, but is required to sort indexes over
541 // multi uint32 keys...
542 if (length1
< length2
)
544 else if (length1
== length2
)
545 return uint32cmp(values1
, values2
, length1
) < 0;
549 CssmError::throwMe(CSSMERR_DL_UNSUPPORTED_QUERY
);