// 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. #ifndef OPEN_VCDIFF_DECODETABLE_H_ #define OPEN_VCDIFF_DECODETABLE_H_ #include <config.h> #include <stddef.h> // NULL #include <stdint.h> // int32_t #include <memory> // auto_ptr #include "codetable.h" // VCDiffInstructi... #include "logging.h" namespace open_vcdiff { // This class is used by the decoder. It can use a standard or // non-standard code table, and will translate the opcodes in the code table // into delta instructions. // // NOT threadsafe. // class VCDiffCodeTableReader { public: // When constructed, the object will be set up to use the default code table. // If a non-default code table is to be used, then UseCodeTable() // should be called after the VCDiffCodeTableReader has been constructed. // In any case, the Init() method must be called before GetNextInstruction() // may be used. // VCDiffCodeTableReader(); // Sets up a non-standard code table. The caller // may free the memory occupied by the argument code table after // passing it to this method, because the argument code table // allocates space to store a copy of it. // UseCodeTable() may be called either before or after calling Init(). // Returns true if the code table was accepted, or false if the // argument did not appear to be a valid code table. // bool UseCodeTable(const VCDiffCodeTableData& code_table_data, unsigned char max_mode); // Defines the buffer containing the instructions and sizes. // This method must be called before GetNextInstruction() may be used. // Init() may be called any number of times to reset the state of // the object. // void Init(const char** instructions_and_sizes, const char* instructions_and_sizes_end) { instructions_and_sizes_ = instructions_and_sizes; instructions_and_sizes_end_ = instructions_and_sizes_end; last_instruction_start_ = NULL; pending_second_instruction_ = kNoOpcode; last_pending_second_instruction_ = kNoOpcode; } // Updates the pointers to the buffer containing the instructions and sizes, // but leaves the rest of the reader state intact, so that (for example) // any pending second instruction or unread instruction will still be // read when requested. NOTE: UnGetInstruction() will not work immediately // after using UpdatePointers(); GetNextInstruction() must be called first. // void UpdatePointers(const char** instructions_and_sizes, const char* instructions_and_sizes_end) { instructions_and_sizes_ = instructions_and_sizes; instructions_and_sizes_end_ = instructions_and_sizes_end; last_instruction_start_ = *instructions_and_sizes; // pending_second_instruction_ is unchanged last_pending_second_instruction_ = pending_second_instruction_; } // Returns the next instruction from the stream of opcodes, // or VCD_INSTRUCTION_END_OF_DATA if the end of the opcode stream is reached, // or VCD_INSTRUCTION_ERROR if an error occurred. // In the first of these cases, increments *instructions_and_sizes_ // past the values it reads, and populates *size // with the corresponding size for the returned instruction; // otherwise, the value of *size is undefined, and is not // guaranteed to be preserved. // If the instruction returned is VCD_COPY, *mode will // be populated with the copy mode; otherwise, the value of *mode // is undefined, and is not guaranteed to be preserved. // Any occurrences of VCD_NOOP in the opcode stream // are skipped over and ignored, not returned. // If Init() was not called before calling this method, then // VCD_INSTRUCTION_ERROR will be returned. // VCDiffInstructionType GetNextInstruction(int32_t* size, unsigned char* mode); // Puts a single instruction back onto the front of the // instruction stream. The next call to GetNextInstruction() // will return the same value that was returned by the last // call. Calling UnGetInstruction() more than once before calling // GetNextInstruction() will have no additional effect; you can // only rewind one instruction. // void UnGetInstruction() { if (last_instruction_start_) { if (last_instruction_start_ > *instructions_and_sizes_) { VCD_DFATAL << "Internal error: last_instruction_start past end of " "instructions_and_sizes in UnGetInstruction" << VCD_ENDL; } *instructions_and_sizes_ = last_instruction_start_; if ((pending_second_instruction_ != kNoOpcode) && (last_pending_second_instruction_ != kNoOpcode)) { VCD_DFATAL << "Internal error: two pending instructions in a row " "in UnGetInstruction" << VCD_ENDL; } pending_second_instruction_ = last_pending_second_instruction_; } } private: // A pointer to the code table. This is the object that will be used // to interpret opcodes in GetNextInstruction(). const VCDiffCodeTableData* code_table_data_; // If the default code table is not being used, then space for the // code table data will be allocated using this pointer and freed // when the VCDiffCodeTableReader is destroyed. This will keep the // code that uses the object from having to worry about memory // management for the non-standard code table, whose contents have // been read as part of the encoded data file/stream. // std::auto_ptr<VCDiffCodeTableData> non_default_code_table_data_; const char** instructions_and_sizes_; const char* instructions_and_sizes_end_; const char* last_instruction_start_; OpcodeOrNone pending_second_instruction_; OpcodeOrNone last_pending_second_instruction_; // Making these private avoids implicit copy constructor & assignment operator VCDiffCodeTableReader(const VCDiffCodeTableReader&); void operator=(const VCDiffCodeTableReader&); }; }; // namespace open_vcdiff #endif // OPEN_VCDIFF_DECODETABLE_H_