Skip to content

Commit b215642

Browse files
committed
Implement comparison logic.
1 parent 061380e commit b215642

File tree

4 files changed

+63
-19
lines changed

4 files changed

+63
-19
lines changed

Firestore/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Unreleased
22
- [feature] Adds support for the following new types: `MinKey`, `MaxKey`, `RegexValue`,
3-
`Int32Value`, `BSONObjectId`, `BSONTimestamp`, and `BSONBinaryData`. (#14800)
3+
`Int32Value`, `Decimal128Value`, `BSONObjectId`, `BSONTimestamp`, and `BSONBinaryData`. (#14800)
44

55
# 11.12.0
66
- [fixed] Fixed the `null` value handling in `isNotEqualTo` and `notIn` filters.

Firestore/Source/API/FIRDecimal128Value.mm

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616

1717
#include "Firestore/Source/Public/FirebaseFirestore/FIRDecimal128Value.h"
1818

19+
#include "Firestore/core/src/util/quadruple.h"
20+
#include "Firestore/core/src/util/string_apple.h"
21+
22+
using firebase::firestore::util::Quadruple;
23+
using firebase::firestore::util::MakeString;
24+
1925
@implementation FIRDecimal128Value
2026

2127
- (instancetype)initWithValue:(NSString *)value {
@@ -36,10 +42,12 @@ - (BOOL)isEqual:(nullable id)object {
3642
}
3743

3844
FIRDecimal128Value *other = (FIRDecimal128Value *)object;
39-
//
40-
// TODO(ehsann): Convert to Quadruple and compare quadruples.
41-
//
42-
return [self.value isEqualToString:other.value];
45+
46+
Quadruple self_quadruple = Quadruple();
47+
Quadruple other_quadruple = Quadruple();
48+
self_quadruple.Parse(MakeString(self.value));
49+
other_quadruple.Parse(MakeString(other.value));
50+
return self_quadruple.Compare(other_quadruple) == 0;
4351
}
4452

4553
- (id)copyWithZone:(__unused NSZone *_Nullable)zone {

Firestore/core/src/model/value_util.cc

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "Firestore/core/src/nanopb/nanopb_util.h"
3131
#include "Firestore/core/src/util/comparison.h"
3232
#include "Firestore/core/src/util/hard_assert.h"
33+
#include "Firestore/core/src/util/quadruple.h"
3334
#include "absl/strings/escaping.h"
3435
#include "absl/strings/str_format.h"
3536
#include "absl/strings/str_join.h"
@@ -41,6 +42,7 @@ namespace model {
4142

4243
using nanopb::Message;
4344
using util::ComparisonResult;
45+
using util::Quadruple;
4446

4547
/** The smallest reference value. */
4648
pb_bytes_array_s* kMinimumReferenceValue =
@@ -259,12 +261,46 @@ void SortFields(google_firestore_v1_Value& value) {
259261
}
260262
}
261263

264+
Quadruple ConvertNumericValueToQuadruple(const google_firestore_v1_Value& value) {
265+
if (value.which_value_type == google_firestore_v1_Value_double_value_tag) {
266+
return Quadruple(value.double_value);
267+
} else if (value.which_value_type == google_firestore_v1_Value_integer_value_tag) {
268+
return Quadruple(value.integer_value);
269+
} else if (IsInt32Value(value)) {
270+
return Quadruple(value.map_value.fields[0].value.integer_value);
271+
} else if (IsDecimal128Value(value)) {
272+
Quadruple result;
273+
result.Parse(nanopb::MakeString(value.map_value.fields[0].value.string_value));
274+
return result;
275+
}
276+
277+
HARD_FAIL("ConvertNumericValueToQuadruple was called with non-numeric value: %s", value.ToString());
278+
}
279+
262280
ComparisonResult Compare128BitNumbers(const google_firestore_v1_Value& left,
263281
const google_firestore_v1_Value& right) {
264-
// TODO: implement.
265-
(void)left;
266-
(void)right;
267-
return ComparisonResult::Same;
282+
Quadruple lhs = ConvertNumericValueToQuadruple(left);
283+
Quadruple rhs = ConvertNumericValueToQuadruple(right);
284+
if (lhs.is_nan()) {
285+
return rhs.is_nan() ? ComparisonResult::Same : ComparisonResult::Ascending;
286+
} else if (rhs.is_nan()) {
287+
// rhs is NaN, but lhs is not.
288+
return ComparisonResult::Descending;
289+
}
290+
291+
// Override negative zero values to positive zero.
292+
Quadruple negative_zero = Quadruple();
293+
negative_zero.Parse("-0");
294+
if (lhs.Compare(negative_zero) == 0) {
295+
lhs = Quadruple();
296+
}
297+
if (rhs.Compare(negative_zero) == 0) {
298+
rhs = Quadruple();
299+
}
300+
301+
// Since `Compare` returns `-1`, `0`, and `1` with the same semantics as the
302+
// `ComparisonResult` enum, we can safely cast it.
303+
return static_cast<ComparisonResult>(lhs.Compare(rhs));
268304
}
269305

270306
ComparisonResult CompareNumbers(const google_firestore_v1_Value& left,

Firestore/core/src/util/quadruple_builder.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ bool is_gte(int64_t s, uint64_t u) {
179179
mantissa[i] = 0;
180180
}
181181
// Skip leading zeroes
182-
uint32_t firstDigit = 0;
183-
while (firstDigit < (digits).size() && digits[firstDigit] == 0) {
182+
int32_t firstDigit = 0;
183+
while (firstDigit < static_cast<int32_t>(digits.size()) && digits[firstDigit] == 0) {
184184
firstDigit += 1;
185185
}
186-
if (firstDigit == (digits).size()) {
186+
if (firstDigit == static_cast<int32_t>(digits.size())) {
187187
return 0; // All zeroes
188188
}
189189
int32_t expCorr = -firstDigit;
@@ -200,7 +200,7 @@ bool is_gte(int64_t s, uint64_t u) {
200200
digits = truncated;
201201
firstDigit = 0;
202202
}
203-
for (uint32_t i = ((digits).size()) - 1; i >= (firstDigit); i--) { // digits, starting from the last
203+
for (int32_t i = static_cast<int32_t>((digits).size()) - 1; i >= (firstDigit); i--) { // digits, starting from the last
204204
mantissa[0] |= (static_cast<uint64_t>(digits[i])) << 32;
205205
divBuffBy10(mantissa);
206206
}
@@ -223,7 +223,7 @@ bool is_gte(int64_t s, uint64_t u) {
223223
// @param buffer the buffer to check
224224
// @return {@code true} if the buffer is empty, {@code false} otherwise
225225
template<std::size_t N> bool QuadrupleBuilder::isEmpty(std::array<uint64_t,N>& buffer) {
226-
for (uint32_t i = (0); i < ((buffer).size()); i++) {
226+
for (size_t i = (0); i < ((buffer).size()); i++) {
227227
if (buffer[i] != 0) {
228228
return false;
229229
}
@@ -340,7 +340,7 @@ bool is_gte(int64_t s, uint64_t u) {
340340
}
341341
// Copies from into to.
342342
template<std::size_t N> void QuadrupleBuilder::array_copy(std::array<uint64_t,N>& source,std::array<uint64_t,4>& dest) {
343-
for (uint32_t i = (0); i < ((dest).size()); i++) {
343+
for (size_t i = (0); i < ((dest).size()); i++) {
344344
dest[i] = source[i];
345345
}
346346
}
@@ -365,7 +365,7 @@ bool is_gte(int64_t s, uint64_t u) {
365365
// @param factor2 an array of longs containing factor 2 as packed quasidecimal
366366
// @param result an array of 12 longs filled with the product of mantissas
367367
void QuadrupleBuilder::multPacked3x64_simply(std::array<uint64_t,4>& factor1,std::array<uint64_t,4>& factor2,std::array<uint64_t,12>& result) {
368-
for (uint32_t i = (0); i < ((result).size()); i++) {
368+
for (size_t i = (0); i < ((result).size()); i++) {
369369
result[i] = 0;
370370
}
371371
// TODO2 19.01.16 21:23:06 for the next version -- rebuild the table of powers to make the
@@ -413,7 +413,7 @@ bool is_gte(int64_t s, uint64_t u) {
413413
// Multiplying a 128-bit number by another 192-bit number,
414414
// as well as multiplying of two 192-bit numbers,
415415
// can never produce 320 (or 384 bits, respectively) of 0x1999_9999L, 0x9999_9999L,
416-
for (uint32_t i = (1); i < ((buffer).size()); i++) {
416+
for (size_t i = (1); i < ((buffer).size()); i++) {
417417
// so this loop can't be covered entirely
418418
if (buffer[i] < 0x99999999LL) {
419419
return true;
@@ -431,7 +431,7 @@ bool is_gte(int64_t s, uint64_t u) {
431431
// @param factor2 an array of 4 longs containing packed quasidecimal power of two
432432
// @param product a buffer of at least 12 longs to hold the product
433433
void QuadrupleBuilder::multUnpacked6x32byPacked(std::array<uint64_t,6>& factor1,std::array<uint64_t,4>& factor2,std::array<uint64_t,12>& product) {
434-
for (uint32_t i = (0); i < ((product).size()); i++) {
434+
for (size_t i = (0); i < ((product).size()); i++) {
435435
product[i] = 0;
436436
}
437437
std::array<uint64_t, 6>& unpacked2 = this->buffer6x32B;
@@ -572,4 +572,4 @@ bool is_gte(int64_t s, uint64_t u) {
572572
}
573573
} // namespace util
574574
} // namespace firestore
575-
} // namespace firebase
575+
} // namespace firebase

0 commit comments

Comments
 (0)