| // Copyright 2008 Google Inc. |
| // Author: Lincoln Smith |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // codetable.cc: |
| // Classes to implement the Code Table |
| // described in sections 5.5, 5.6 and 7 of |
| // RFC 3284 - The VCDIFF Generic Differencing and Compression Data Format. |
| // The RFC text can be found at http://www.faqs.org/rfcs/rfc3284.html |
| |
| #include <config.h> |
| #include "addrcache.h" |
| #include "codetable.h" |
| #include "logging.h" |
| #include "vcdiff_defs.h" // VCD_MAX_MODES |
| |
| namespace open_vcdiff { |
| |
| const char* VCDiffInstructionName(VCDiffInstructionType inst) { |
| switch (inst) { |
| case VCD_NOOP: |
| return "NOOP"; |
| case VCD_ADD: |
| return "ADD"; |
| case VCD_RUN: |
| return "RUN"; |
| case VCD_COPY: |
| return "COPY"; |
| default: |
| LOG(ERROR) << "Unexpected instruction type " << inst << LOG_ENDL; |
| return ""; |
| } |
| } |
| |
| // This is the default code table defined in the RFC, section 5.6. |
| // Using a static struct means that the compiler will do the work of |
| // laying out the values in memory rather than having to use loops to do so |
| // at runtime. The letters "N", "A", "R", and "C" are defined as VCD_NOOP, |
| // VCD_ADD, VCD_RUN, and VCD_COPY respectively (see the definition of |
| // struct VCDiffCodeTableData), which allows for a compact |
| // representation of the code table data. |
| // |
| const VCDiffCodeTableData VCDiffCodeTableData::kDefaultCodeTableData = |
| // inst1 |
| { { R, // opcode 0 |
| A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 1-18 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 19-34 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 35-50 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 51-66 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 67-82 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 83-98 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 99-114 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 115-130 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 131-146 |
| C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 147-162 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 163-174 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 175-186 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 187-198 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 199-210 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 211-222 |
| A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 223-234 |
| A, A, A, A, // opcodes 235-238 |
| A, A, A, A, // opcodes 239-242 |
| A, A, A, A, // opcodes 243-246 |
| C, C, C, C, C, C, C, C, C }, // opcodes 247-255 |
| // inst2 |
| { N, // opcode 0 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 1-18 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 19-34 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 35-50 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 51-66 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 67-82 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 83-98 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 99-114 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 115-130 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 131-146 |
| N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 147-162 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 163-174 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 175-186 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 187-198 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 199-210 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 211-222 |
| C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 223-234 |
| C, C, C, C, // opcodes 235-238 |
| C, C, C, C, // opcodes 239-242 |
| C, C, C, C, // opcodes 243-246 |
| A, A, A, A, A, A, A, A, A }, // opcodes 247-255 |
| // size1 |
| { 0, // opcode 0 |
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // 1-18 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 19-34 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 35-50 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 51-66 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 67-82 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 83-98 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 99-114 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 115-130 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 131-146 |
| 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 147-162 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 163-174 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 175-186 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 187-198 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 199-210 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 211-222 |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 223-234 |
| 1, 2, 3, 4, // opcodes 235-238 |
| 1, 2, 3, 4, // opcodes 239-242 |
| 1, 2, 3, 4, // opcodes 243-246 |
| 4, 4, 4, 4, 4, 4, 4, 4, 4 }, // opcodes 247-255 |
| // size2 |
| { 0, // opcode 0 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 35-50 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 51-66 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 67-82 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 83-98 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 99-114 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 115-130 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 131-146 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 147-162 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 163-174 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 175-186 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 187-198 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 199-210 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 211-222 |
| 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 223-234 |
| 4, 4, 4, 4, // opcodes 235-238 |
| 4, 4, 4, 4, // opcodes 239-242 |
| 4, 4, 4, 4, // opcodes 243-246 |
| 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // opcodes 247-255 |
| // mode1 |
| { 0, // opcode 0 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // opcodes 35-50 |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // opcodes 51-66 |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // opcodes 67-82 |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // opcodes 83-98 |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // opcodes 99-114 |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // opcodes 115-130 |
| 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // opcodes 131-146 |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // opcodes 147-162 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 163-174 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 175-186 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 187-198 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 199-210 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 211-222 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 223-234 |
| 0, 0, 0, 0, // opcodes 235-238 |
| 0, 0, 0, 0, // opcodes 239-242 |
| 0, 0, 0, 0, // opcodes 243-246 |
| 0, 1, 2, 3, 4, 5, 6, 7, 8 }, // opcodes 247-255 |
| // mode2 |
| { 0, // opcode 0 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 35-50 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 51-66 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 67-82 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 83-98 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 99-114 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 115-130 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 131-146 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 147-162 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 163-174 |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // opcodes 175-186 |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // opcodes 187-198 |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // opcodes 199-210 |
| 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // opcodes 211-222 |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // opcodes 223-234 |
| 6, 6, 6, 6, // opcodes 235-238 |
| 7, 7, 7, 7, // opcodes 239-242 |
| 8, 8, 8, 8, // opcodes 243-246 |
| 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; // opcodes 247-255 |
| |
| bool VCDiffCodeTableData::ValidateOpcode(int opcode, |
| unsigned char inst, |
| unsigned char size, |
| unsigned char mode, |
| unsigned char max_mode, |
| const char* first_or_second) { |
| bool no_errors_found = true; |
| // Check upper limits of inst and mode. inst, size, and mode are |
| // unsigned, so there is no lower limit on them. |
| if (inst > VCD_LAST_INSTRUCTION_TYPE) { |
| LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has invalid " |
| << first_or_second << " instruction type " |
| << static_cast<int>(inst) << LOG_ENDL; |
| no_errors_found = false; |
| } |
| if (mode > max_mode) { |
| LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has invalid " |
| << first_or_second << " mode " |
| << static_cast<int>(mode) << LOG_ENDL; |
| no_errors_found = false; |
| } |
| // A NOOP instruction must have size 0 |
| // (and mode 0, which is included in the next rule) |
| if ((inst == VCD_NOOP) && (size != 0)) { |
| LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has " |
| << first_or_second << " instruction NOOP with nonzero size " |
| << static_cast<int>(size) << LOG_ENDL; |
| no_errors_found = false; |
| } |
| // A nonzero mode can only be used with a COPY instruction |
| if ((inst != VCD_COPY) && (mode != 0)) { |
| LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode |
| << " has non-COPY " |
| << first_or_second << " instruction with nonzero mode " |
| << static_cast<int>(mode) << LOG_ENDL; |
| no_errors_found = false; |
| } |
| return no_errors_found; |
| } |
| |
| // If an error is found while validating, continue to validate the rest |
| // of the code table so that all validation errors will appear in |
| // the error log. Otherwise the user would have to fix a single error |
| // and then rerun validation to find the next error. |
| // |
| bool VCDiffCodeTableData::Validate(unsigned char max_mode) const { |
| const int kNumberOfTypesAndModes = VCD_LAST_INSTRUCTION_TYPE + max_mode + 1; |
| bool hasOpcodeForTypeAndMode[VCD_LAST_INSTRUCTION_TYPE + VCD_MAX_MODES]; |
| bool no_errors_found = true; |
| for (int i = 0; i < kNumberOfTypesAndModes; ++i) { |
| hasOpcodeForTypeAndMode[i] = false; |
| } |
| for (int i = 0; i < kCodeTableSize; ++i) { |
| no_errors_found = |
| ValidateOpcode(i, inst1[i], size1[i], mode1[i], max_mode, "first") |
| && no_errors_found; // use as 2nd operand to avoid short-circuit |
| no_errors_found = |
| ValidateOpcode(i, inst2[i], size2[i], mode2[i], max_mode, "second") |
| && no_errors_found; |
| // A valid code table must have an opcode to encode every possible |
| // combination of inst and mode with size=0 as its first instruction, |
| // and NOOP as its second instruction. If this condition fails, |
| // then there exists a set of input instructions that cannot be encoded. |
| if ((size1[i] == 0) && |
| (inst2[i] == VCD_NOOP) && |
| ((static_cast<int>(inst1[i]) + static_cast<int>(mode1[i])) |
| < kNumberOfTypesAndModes)) { |
| hasOpcodeForTypeAndMode[inst1[i] + mode1[i]] = true; |
| } |
| } |
| for (int i = 0; i < kNumberOfTypesAndModes; ++i) { |
| if (i == VCD_NOOP) continue; |
| if (!hasOpcodeForTypeAndMode[i]) { |
| if (i >= VCD_COPY) { |
| LOG(ERROR) << "VCDiff: Bad code table; there is no opcode for inst " |
| "COPY, size 0, mode " << (i - VCD_COPY) << LOG_ENDL; |
| } else { |
| LOG(ERROR) << "VCDiff: Bad code table; there is no opcode for inst " |
| << VCDiffInstructionName(static_cast<VCDiffInstructionType>(i)) |
| << ", size 0, mode 0" << LOG_ENDL; |
| } |
| no_errors_found = false; |
| } |
| } |
| return no_errors_found; |
| } |
| |
| bool VCDiffCodeTableData::Validate() const { |
| return Validate(VCDiffAddressCache::DefaultLastMode()); |
| } |
| |
| } // namespace open_vcdiff |