Skip to content

Commit fc25d0f

Browse files
committed
Merge branch 'fix_consecutive_strings' into pr_for_google
2 parents a380d16 + 00c4232 commit fc25d0f

3 files changed

Lines changed: 97 additions & 0 deletions

File tree

google/cloud/bigtable/emulator/range_set.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <algorithm>
2222
#include <cassert>
2323
#include <chrono>
24+
#include <iterator>
2425
#include <ostream>
2526
#include <string>
2627

@@ -573,6 +574,52 @@ std::ostream& operator<<(std::ostream& os,
573574
return os;
574575
}
575576

577+
bool ConsecutiveStringsOfMaxLen(std::string const& a, std::string const& b,
578+
std::size_t max_len) {
579+
assert(a.length() <= max_len);
580+
assert(b.length() <= max_len);
581+
582+
if (max_len == 0) {
583+
return false;
584+
}
585+
586+
if (a.length() < max_len) {
587+
return internal::ConsecutiveRowKeys(a, b);
588+
}
589+
590+
// Note that at this point we are guaranteed that a is not empty but
591+
// let us be sure.
592+
assert(!a.empty());
593+
594+
// What is the rightmost index that we can increment by 1 to get
595+
// the next string in lexicographic order.
596+
absl::optional<std::size_t> index_to_inc = absl::nullopt;
597+
598+
for (auto it = a.rbegin(); it != a.rend(); it++) {
599+
char c = *it;
600+
if (c < CHAR_MAX) {
601+
index_to_inc = (a.length() - 1) - std::distance(a.rbegin(), it);
602+
break;
603+
}
604+
}
605+
606+
if (!index_to_inc.has_value()) {
607+
// a is the last string in lexicographical order for strings of
608+
// max_len chars, so it has no successor.
609+
return false;
610+
}
611+
612+
std::string successor_to_a;
613+
// A copy but if we want we could fix that by a comparison in 3
614+
// parts. However, row keys that are at maximum length are the rare
615+
// exception, presumably.
616+
successor_to_a = a;
617+
618+
successor_to_a[index_to_inc.value()] += 1;
619+
620+
return successor_to_a == b;
621+
}
622+
576623
} // namespace emulator
577624
} // namespace bigtable
578625
} // namespace cloud

google/cloud/bigtable/emulator/range_set.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ bool operator==(TimestampRangeSet::Range const& lhs,
191191
std::ostream& operator<<(std::ostream& os,
192192
TimestampRangeSet::Range const& range);
193193

194+
bool ConsecutiveStringsOfMaxLen(std::string const& a, std::string const& b,
195+
std::size_t max_len);
196+
194197
// For testing only.
195198
namespace detail {
196199

google/cloud/bigtable/emulator/range_set_test.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <gtest/gtest.h>
2020
#include <algorithm>
2121
#include <chrono>
22+
#include <climits>
2223
#include <iterator>
2324
#include <set>
2425
#include <sstream>
@@ -816,6 +817,52 @@ TEST(StringRangeSet, IntersectDistinct) {
816817
ASSERT_EQ(empty, srs.disjoint_ranges());
817818
}
818819

820+
TEST(ConsecutiveStringsOfMaxLen, ZeroLen) {
821+
std::string a;
822+
std::string b;
823+
824+
ASSERT_FALSE(ConsecutiveStringsOfMaxLen(a, b, 0));
825+
}
826+
827+
TEST(ConsecutiveStringsOfMaxLen, ShorterThanMaxLen) {
828+
std::string a;
829+
std::string b;
830+
b.push_back('\0');
831+
832+
ASSERT_TRUE(ConsecutiveStringsOfMaxLen(a, b, 1));
833+
834+
a = "a";
835+
b = "a";
836+
b.push_back('\0');
837+
838+
ASSERT_TRUE(ConsecutiveStringsOfMaxLen(a, b, 2));
839+
}
840+
841+
TEST(ConsecutiveStringsOfMaxLen, FirstHasMaxLen) {
842+
std::string a = "a";
843+
std::string b = "b";
844+
845+
ASSERT_TRUE(ConsecutiveStringsOfMaxLen(a, b, 1));
846+
847+
a = "a";
848+
b = "c";
849+
850+
ASSERT_FALSE(ConsecutiveStringsOfMaxLen(a, b, 1));
851+
852+
// Test the case where the first string is at max length and the
853+
// terminal char or chars cannot be incremented because they are at
854+
// maximum value.
855+
a = "a";
856+
a.push_back(CHAR_MAX);
857+
a.push_back(CHAR_MAX);
858+
859+
b = "b";
860+
b.push_back(CHAR_MAX);
861+
b.push_back(CHAR_MAX);
862+
863+
ASSERT_TRUE(ConsecutiveStringsOfMaxLen(a, b, 3));
864+
}
865+
819866
} // anonymous namespace
820867
} // namespace emulator
821868
} // namespace bigtable

0 commit comments

Comments
 (0)