1 /* 2 * Copyright (C) 2015, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <algorithm> 18 #include <iostream> 19 #include <iterator> 20 21 #include <android-base/strings.h> 22 23 #include "os.h" 24 #include "tests/test_util.h" 25 26 using android::base::Split; 27 using android::base::Join; 28 using std::string; 29 using std::vector; 30 using std::cout; 31 using std::endl; 32 using std::distance; 33 34 namespace android { 35 namespace aidl { 36 namespace test { 37 38 string CanonicalNameToPath(const char* package_class, const char* extension) { 39 string rel_path{package_class}; 40 for (char& c : rel_path) { 41 if (c == '.') { 42 c = OS_PATH_SEPARATOR; 43 } 44 } 45 rel_path += extension; 46 return rel_path; 47 } 48 49 void SplitPackageClass(const string& package_class, 50 string* rel_path, 51 string* package, 52 string* class_name) { 53 *package = string{package_class, 0, package_class.rfind('.')}; 54 *class_name = string{package_class, package_class.rfind('.') + 1}; 55 *rel_path = CanonicalNameToPath(package_class.c_str(), ".aidl"); 56 } 57 58 void PrintDiff(const string& a, const string& b) { 59 const int LEFT = 1; 60 const int UP = 2; 61 const int UP_LEFT = 4; 62 63 auto a_lines = Split(a, "\n"); 64 auto b_lines = Split(b, "\n"); 65 66 struct diff_table_entry { 67 size_t longest_common_subsequence_length; 68 int propagation_directions; 69 }; 70 71 diff_table_entry table[a_lines.size() + 1][b_lines.size() + 1]; 72 73 for (size_t i = 0; i < a_lines.size() + 1; ++i) { 74 for (size_t j = 0; j < b_lines.size() + 1; ++j) { 75 if (i == 0 || j == 0) { 76 int directions = 0; 77 78 if (i) { 79 directions |= UP; 80 } 81 82 if (j) { 83 directions |= LEFT; 84 } 85 86 table[i][j].longest_common_subsequence_length = 0; 87 table[i][j].propagation_directions = directions; 88 } else if (a_lines[i-1] == b_lines[j-1]) { 89 table[i][j].longest_common_subsequence_length = 90 table[i-1][j-1].longest_common_subsequence_length + 1; 91 table[i][j].propagation_directions = UP_LEFT; 92 } else { 93 size_t length_up = table[i-1][j].longest_common_subsequence_length; 94 size_t length_left = table[i][j-1].longest_common_subsequence_length; 95 int directions = 0; 96 size_t length; 97 98 if (length_up >= length_left) { 99 directions |= UP; 100 length = length_up; 101 } 102 103 if (length_left >= length_up) { 104 directions |= LEFT; 105 length = length_left; 106 } 107 108 table[i][j].longest_common_subsequence_length = length; 109 table[i][j].propagation_directions = directions; 110 } 111 } 112 } 113 114 size_t i = a_lines.size(); 115 size_t j = b_lines.size(); 116 vector<string> output; 117 118 while (table[i][j].propagation_directions) { 119 if (table[i][j].propagation_directions & UP_LEFT) { 120 output.push_back(" " + a_lines[i-1]); 121 i--; 122 j--; 123 } else if (table[i][j].propagation_directions & UP) { 124 output.push_back("-" + a_lines[i-1]); 125 i--; 126 } else { 127 output.push_back("+" + b_lines[j-1]); 128 j--; 129 } 130 } 131 132 int print_mask = 0; 133 bool printed_last = false; 134 size_t line_number = 0; 135 136 for (auto it = output.crbegin(), frontier = output.crbegin(); 137 it != output.crend(); ++it) { 138 while (frontier != output.crend() && distance(it, frontier) <= 3) { 139 print_mask <<= 1; 140 print_mask &= 0x7f; 141 142 if ((*frontier)[0] != ' ') { 143 print_mask |= 1; 144 } 145 146 frontier++; 147 } 148 149 if ((*it)[0] != '-') { 150 line_number++; 151 } 152 153 if (print_mask) { 154 if (!printed_last) { 155 cout << "Line: " << line_number << endl; 156 } 157 158 cout << *it << endl; 159 printed_last = true; 160 } else { 161 printed_last = false; 162 } 163 } 164 } 165 166 } // namespace test 167 } // namespace android 168 } // namespace aidl 169