10a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Copyright 2008 Google Inc. 20a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Author: Lincoln Smith 30a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 40a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Licensed under the Apache License, Version 2.0 (the "License"); 50a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// you may not use this file except in compliance with the License. 60a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// You may obtain a copy of the License at 70a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 80a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// http://www.apache.org/licenses/LICENSE-2.0 90a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Unless required by applicable law or agreed to in writing, software 110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// distributed under the License is distributed on an "AS IS" BASIS, 120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// See the License for the specific language governing permissions and 140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// limitations under the License. 150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// VCDiffCodeTableReader is a class to interpret a stream of opcodes 170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// as VCDIFF instruction types, based on a VCDiffCodeTableData structure. 180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <config.h> 200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "decodetable.h" 210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "codetable.h" 220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "logging.h" 230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "varint_bigendian.h" 240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "vcdiff_defs.h" 250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathnamespace open_vcdiff { 270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffCodeTableReader::VCDiffCodeTableReader() 290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath : code_table_data_(&VCDiffCodeTableData::kDefaultCodeTableData), 300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath non_default_code_table_data_(NULL), 310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_(NULL), 320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_end_(NULL), 330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_instruction_start_(NULL), 340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath pending_second_instruction_(kNoOpcode), 350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_pending_second_instruction_(kNoOpcode) { 360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffCodeTableReader::UseCodeTable( 390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const VCDiffCodeTableData& code_table_data, unsigned char max_mode) { 400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!code_table_data.Validate(max_mode)) return false; 410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!non_default_code_table_data_.get()) { 420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath non_default_code_table_data_.reset(new VCDiffCodeTableData); 430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *non_default_code_table_data_ = code_table_data; 450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath code_table_data_ = non_default_code_table_data_.get(); 460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffInstructionType VCDiffCodeTableReader::GetNextInstruction( 500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t* size, 510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char* mode) { 520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!instructions_and_sizes_) { 530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Internal error: GetNextInstruction() called before Init()" 540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return VCD_INSTRUCTION_ERROR; 560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_instruction_start_ = *instructions_and_sizes_; 580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath last_pending_second_instruction_ = pending_second_instruction_; 590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char opcode = 0; 600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char instruction_type = VCD_NOOP; 610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t instruction_size = 0; 620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char instruction_mode = 0; 630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath do { 640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (pending_second_instruction_ != kNoOpcode) { 650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // There is a second instruction left over 660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // from the most recently processed opcode. 670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath opcode = static_cast<unsigned char>(pending_second_instruction_); 680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath pending_second_instruction_ = kNoOpcode; 690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_type = code_table_data_->inst2[opcode]; 700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_size = code_table_data_->size2[opcode]; 710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_mode = code_table_data_->mode2[opcode]; 720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (*instructions_and_sizes_ >= instructions_and_sizes_end_) { 750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Ran off end of instruction stream 760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return VCD_INSTRUCTION_END_OF_DATA; 770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath opcode = **instructions_and_sizes_; 790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (code_table_data_->inst2[opcode] != VCD_NOOP) { 800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This opcode contains two instructions; process the first one now, and 810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // save a pointer to the second instruction, which should be returned 820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // by the next call to GetNextInstruction 830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath pending_second_instruction_ = **instructions_and_sizes_; 840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ++(*instructions_and_sizes_); 860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_type = code_table_data_->inst1[opcode]; 870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_size = code_table_data_->size1[opcode]; 880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instruction_mode = code_table_data_->mode1[opcode]; 890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This do-while loop is necessary in case inst1 == VCD_NOOP for an opcode 900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // that was actually used in the encoding. That case is unusual, but it 910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // is not prohibited by the standard. 920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } while (instruction_type == VCD_NOOP); 930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (instruction_size == 0) { 940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Parse the size as a Varint in the instruction stream. 950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (*size = VarintBE<int32_t>::Parse(instructions_and_sizes_end_, 960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_)) { 970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Instruction size is not a valid variable-length integer" 990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return VCD_INSTRUCTION_ERROR; 1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UnGetInstruction(); // Rewind to instruction start 1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return VCD_INSTRUCTION_END_OF_DATA; 1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; // Successfully parsed Varint 1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *size = instruction_size; 1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *mode = instruction_mode; 1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return static_cast<VCDiffInstructionType>(instruction_type); 1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}; // namespace open_vcdiff 115