// 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