@@ -434,17 +434,13 @@ bool HasVector(const Variant& variant) {
434434 return false ;
435435}
436436
437- bool ParseInteger (const char * str, int32_t * output) {
437+ bool ParseInteger (const char * str, int64_t * output) {
438438 assert (output);
439439 assert (str);
440- // Integers must not have leading zeroes.
441- if (str[0 ] == ' 0' && str[1 ] != ' \0 ' ) {
442- return false ;
443- }
444440 // Check if the key is numeric
445441 bool is_int = false ;
446442 char * end_ptr = nullptr ;
447- int32_t parse_value = strtol (str, &end_ptr, 10 ); // NOLINT
443+ int64_t parse_value = strtoll (str, &end_ptr, 10 ); // NOLINT
448444 if (end_ptr != nullptr && end_ptr != str && *end_ptr == ' \0 ' ) {
449445 is_int = true ;
450446 *output = parse_value;
@@ -454,7 +450,7 @@ bool ParseInteger(const char* str, int32_t* output) {
454450
455451// A Variant map can be converted into a Variant vector if:
456452// 1. map is not empty and
457- // 2. All the key are numeric and
453+ // 2. All the key are integer (no leading 0) and
458454// 3. If less or equal to half of the keys in the array is missing.
459455// Return whether the map can be converted into a vector, and output
460456// max_index_out as the highest numeric key found in the map.
@@ -464,8 +460,14 @@ bool CanConvertVariantMapToVector(const Variant& variant,
464460
465461 int64_t max_index = -1 ;
466462 for (auto & it_child : variant.map ()) {
463+ assert (it_child.first .is_string ());
464+ // Integers must not have leading zeroes.
465+ if (it_child.first .string_value ()[0 ] == ' 0' &&
466+ it_child.first .string_value ()[1 ] != ' \0 ' ) {
467+ return false ;
468+ }
467469 // Check if the key is numeric
468- int32_t parse_value = 0 ;
470+ int64_t parse_value = 0 ;
469471 bool is_number = ParseInteger (it_child.first .string_value (), &parse_value);
470472 if (!is_number || parse_value < 0 ) {
471473 // If any one of the key is not numeric, there is no need to verify
@@ -835,26 +837,55 @@ UtilLeafType GetLeafType(Variant::Type type) {
835837// Store the pointers to the key and the value Variant in a map for sorting
836838typedef std::pair<const Variant*, const Variant*> NodeSortingData;
837839
838- // Comparer for std::sort to sort nodes by key as numeric value
839- // Return true if right node is greater than left node
840- bool KeyAsNumberSortingFunction (const NodeSortingData& left,
841- const NodeSortingData& right) {
842- return left.first ->AsInt64 ().int64_value () <
843- right.first ->AsInt64 ().int64_value ();
840+ int ChildKeyCompareTo (const Variant& left, const Variant& right) {
841+ const Variant kMinChildKey (QueryParamsComparator::kMinKey );
842+ const Variant kMaxChildKey (QueryParamsComparator::kMaxKey );
843+
844+ FIREBASE_DEV_ASSERT (left.is_string ());
845+ FIREBASE_DEV_ASSERT (right.is_string ());
846+
847+ if (left == right) {
848+ return 0 ;
849+ } else if (left == kMinChildKey || right == kMaxChildKey ) {
850+ return -1 ;
851+ } else if (right == kMinChildKey || left == kMaxChildKey ) {
852+ return 1 ;
853+ } else {
854+ int64_t left_int_key = -1 ;
855+ bool left_is_int = ParseInteger (left.string_value (), &left_int_key);
856+ int64_t right_int_key = -1 ;
857+ bool right_is_int = ParseInteger (right.string_value (), &right_int_key);
858+ if (left_is_int) {
859+ if (right_is_int) {
860+ int cmp = left_int_key - right_int_key;
861+ return cmp == 0 ? (strlen (left.string_value ()) -
862+ strlen (right.string_value ()))
863+ : cmp;
864+ } else {
865+ return -1 ;
866+ }
867+ } else if (right_is_int) {
868+ return 1 ;
869+ } else {
870+ return left > right ? 1 : -1 ;
871+ }
872+ }
844873}
845874
846875// Private function to serialize all child nodes
847876void ProcessChildNodes (std::stringstream* ss,
848- std::vector<NodeSortingData>* nodes, bool saw_priority,
849- bool can_convert_vector) {
877+ std::vector<NodeSortingData>* nodes, bool saw_priority) {
850878 // If any node has priority, sort using priority.
851879 if (saw_priority) {
852880 QueryParams params;
853881 assert (params.order_by == QueryParams::kOrderByPriority );
854882 std::sort (nodes->begin (), nodes->end (), QueryParamsLesser (¶ms));
855- } else if (can_convert_vector) {
856- // If the nodes can be converted to a vector, sort using key as number.
857- std::sort (nodes->begin (), nodes->end (), KeyAsNumberSortingFunction);
883+ } else {
884+ // Otherwise, use default sorting function.
885+ std::sort (nodes->begin (), nodes->end (),
886+ [](const NodeSortingData& left, const NodeSortingData& right) {
887+ return ChildKeyCompareTo (*left.first , *right.first ) < 0 ;
888+ });
858889 }
859890
860891 // Serialize each child with its key and its hashed value
@@ -888,16 +919,15 @@ void AppendHashRepAsContainer(std::stringstream* ss, const Variant& data) {
888919 saw_priority =
889920 saw_priority || !GetVariantPriority (data.vector ()[i]).is_null ();
890921 }
891- ProcessChildNodes (ss, &nodes, saw_priority, true );
922+ ProcessChildNodes (ss, &nodes, saw_priority);
892923 } else if (data.is_map ()) {
893924 bool saw_priority = false ;
894925 for (auto & it_child : data.map ()) {
895926 nodes.push_back (NodeSortingData (&it_child.first , &it_child.second ));
896927 saw_priority =
897928 saw_priority || !GetVariantPriority (it_child.second ).is_null ();
898929 }
899- bool can_convert_vector = CanConvertVariantMapToVector (data, nullptr );
900- ProcessChildNodes (ss, &nodes, saw_priority, can_convert_vector);
930+ ProcessChildNodes (ss, &nodes, saw_priority);
901931 }
902932}
903933
0 commit comments