| Index: src/liveedit.cc
|
| diff --git a/src/liveedit.cc b/src/liveedit.cc
|
| index e89cae3ac95fbde6230423ae6efec21181826338..3ebcdbfdb6ef81aab1ac029f69a36975ab06ff2e 100644
|
| --- a/src/liveedit.cc
|
| +++ b/src/liveedit.cc
|
| @@ -66,7 +66,7 @@ void SetElementNonStrict(Handle<JSObject> object,
|
| class Differencer {
|
| public:
|
| explicit Differencer(Comparator::Input* input)
|
| - : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) {
|
| + : input_(input), len1_(input->GetLength1()), len2_(input->GetLength2()) {
|
| buffer_ = NewArray<int>(len1_ * len2_);
|
| }
|
| ~Differencer() {
|
| @@ -151,7 +151,7 @@ class Differencer {
|
| if (cached_res == kEmptyCellValue) {
|
| Direction dir;
|
| int res;
|
| - if (input_->equals(pos1, pos2)) {
|
| + if (input_->Equals(pos1, pos2)) {
|
| res = CompareUpToTail(pos1 + 1, pos2 + 1);
|
| dir = EQ;
|
| } else {
|
| @@ -279,6 +279,70 @@ static bool CompareSubstrings(Handle<String> s1, int pos1,
|
| }
|
|
|
|
|
| +// Additional to Input interface. Lets switch Input range to subrange.
|
| +// More elegant way would be to wrap one Input as another Input object
|
| +// and translate positions there, but that would cost us additional virtual
|
| +// call per comparison.
|
| +class SubrangableInput : public Comparator::Input {
|
| + public:
|
| + virtual void SetSubrange1(int offset, int len) = 0;
|
| + virtual void SetSubrange2(int offset, int len) = 0;
|
| +};
|
| +
|
| +
|
| +class SubrangableOutput : public Comparator::Output {
|
| + public:
|
| + virtual void SetSubrange1(int offset, int len) = 0;
|
| + virtual void SetSubrange2(int offset, int len) = 0;
|
| +};
|
| +
|
| +
|
| +static int min(int a, int b) {
|
| + return a < b ? a : b;
|
| +}
|
| +
|
| +
|
| +// Finds common prefix and suffix in input. This parts shouldn't take space in
|
| +// linear programming table. Enable subranging in input and output.
|
| +static void NarrowDownInput(SubrangableInput* input,
|
| + SubrangableOutput* output) {
|
| + const int len1 = input->GetLength1();
|
| + const int len2 = input->GetLength2();
|
| +
|
| + int common_prefix_len;
|
| + int common_suffix_len;
|
| +
|
| + {
|
| + common_prefix_len = 0;
|
| + int prefix_limit = min(len1, len2);
|
| + while (common_prefix_len < prefix_limit &&
|
| + input->Equals(common_prefix_len, common_prefix_len)) {
|
| + common_prefix_len++;
|
| + }
|
| +
|
| + common_suffix_len = 0;
|
| + int suffix_limit = min(len1 - common_prefix_len, len2 - common_prefix_len);
|
| +
|
| + while (common_suffix_len < suffix_limit &&
|
| + input->Equals(len1 - common_suffix_len - 1,
|
| + len2 - common_suffix_len - 1)) {
|
| + common_suffix_len++;
|
| + }
|
| + }
|
| +
|
| + if (common_prefix_len > 0 || common_suffix_len > 0) {
|
| + int new_len1 = len1 - common_suffix_len - common_prefix_len;
|
| + int new_len2 = len2 - common_suffix_len - common_prefix_len;
|
| +
|
| + input->SetSubrange1(common_prefix_len, new_len1);
|
| + input->SetSubrange2(common_prefix_len, new_len2);
|
| +
|
| + output->SetSubrange1(common_prefix_len, new_len1);
|
| + output->SetSubrange2(common_prefix_len, new_len2);
|
| + }
|
| +}
|
| +
|
| +
|
| // A helper class that writes chunk numbers into JSArray.
|
| // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end).
|
| class CompareOutputArrayWriter {
|
| @@ -319,13 +383,13 @@ class TokensCompareInput : public Comparator::Input {
|
| : s1_(s1), offset1_(offset1), len1_(len1),
|
| s2_(s2), offset2_(offset2), len2_(len2) {
|
| }
|
| - virtual int getLength1() {
|
| + virtual int GetLength1() {
|
| return len1_;
|
| }
|
| - virtual int getLength2() {
|
| + virtual int GetLength2() {
|
| return len2_;
|
| }
|
| - bool equals(int index1, int index2) {
|
| + bool Equals(int index1, int index2) {
|
| return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
|
| }
|
|
|
| @@ -401,20 +465,26 @@ class LineEndsWrapper {
|
|
|
|
|
| // Represents 2 strings as 2 arrays of lines.
|
| -class LineArrayCompareInput : public Comparator::Input {
|
| +class LineArrayCompareInput : public SubrangableInput {
|
| public:
|
| LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
|
| LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
|
| : s1_(s1), s2_(s2), line_ends1_(line_ends1),
|
| - line_ends2_(line_ends2) {
|
| + line_ends2_(line_ends2),
|
| + subrange_offset1_(0), subrange_offset2_(0),
|
| + subrange_len1_(line_ends1_.length()),
|
| + subrange_len2_(line_ends2_.length()) {
|
| }
|
| - int getLength1() {
|
| - return line_ends1_.length();
|
| + int GetLength1() {
|
| + return subrange_len1_;
|
| }
|
| - int getLength2() {
|
| - return line_ends2_.length();
|
| + int GetLength2() {
|
| + return subrange_len2_;
|
| }
|
| - bool equals(int index1, int index2) {
|
| + bool Equals(int index1, int index2) {
|
| + index1 += subrange_offset1_;
|
| + index2 += subrange_offset2_;
|
| +
|
| int line_start1 = line_ends1_.GetLineStart(index1);
|
| int line_start2 = line_ends2_.GetLineStart(index2);
|
| int line_end1 = line_ends1_.GetLineEnd(index1);
|
| @@ -427,26 +497,42 @@ class LineArrayCompareInput : public Comparator::Input {
|
| return CompareSubstrings(s1_, line_start1, s2_, line_start2,
|
| len1);
|
| }
|
| + void SetSubrange1(int offset, int len) {
|
| + subrange_offset1_ = offset;
|
| + subrange_len1_ = len;
|
| + }
|
| + void SetSubrange2(int offset, int len) {
|
| + subrange_offset2_ = offset;
|
| + subrange_len2_ = len;
|
| + }
|
|
|
| private:
|
| Handle<String> s1_;
|
| Handle<String> s2_;
|
| LineEndsWrapper line_ends1_;
|
| LineEndsWrapper line_ends2_;
|
| + int subrange_offset1_;
|
| + int subrange_offset2_;
|
| + int subrange_len1_;
|
| + int subrange_len2_;
|
| };
|
|
|
|
|
| // Stores compare result in JSArray. For each chunk tries to conduct
|
| // a fine-grained nested diff token-wise.
|
| -class TokenizingLineArrayCompareOutput : public Comparator::Output {
|
| +class TokenizingLineArrayCompareOutput : public SubrangableOutput {
|
| public:
|
| TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
|
| LineEndsWrapper line_ends2,
|
| Handle<String> s1, Handle<String> s2)
|
| - : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2) {
|
| + : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
|
| + subrange_offset1_(0), subrange_offset2_(0) {
|
| }
|
|
|
| void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
|
| + line_pos1 += subrange_offset1_;
|
| + line_pos2 += subrange_offset2_;
|
| +
|
| int char_pos1 = line_ends1_.GetLineStart(line_pos1);
|
| int char_pos2 = line_ends2_.GetLineStart(line_pos2);
|
| int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
|
| @@ -466,6 +552,12 @@ class TokenizingLineArrayCompareOutput : public Comparator::Output {
|
| array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
|
| }
|
| }
|
| + void SetSubrange1(int offset, int len) {
|
| + subrange_offset1_ = offset;
|
| + }
|
| + void SetSubrange2(int offset, int len) {
|
| + subrange_offset2_ = offset;
|
| + }
|
|
|
| Handle<JSArray> GetResult() {
|
| return array_writer_.GetResult();
|
| @@ -479,6 +571,8 @@ class TokenizingLineArrayCompareOutput : public Comparator::Output {
|
| LineEndsWrapper line_ends2_;
|
| Handle<String> s1_;
|
| Handle<String> s2_;
|
| + int subrange_offset1_;
|
| + int subrange_offset2_;
|
| };
|
|
|
|
|
| @@ -493,6 +587,8 @@ Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
|
| LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
|
| TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
|
|
|
| + NarrowDownInput(&input, &output);
|
| +
|
| Comparator::CalculateDifference(&input, &output);
|
|
|
| return output.GetResult();
|
|
|