1 // Copyright 2008 Google Inc. 2 // Author: Lincoln Smith 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 #ifndef OPEN_VCDIFF_DECODETABLE_H_ 17 #define OPEN_VCDIFF_DECODETABLE_H_ 18 19 #include <config.h> 20 #include <stddef.h> // NULL 21 #include <stdint.h> // int32_t 22 #include <memory> // auto_ptr 23 #include "codetable.h" // VCDiffInstructi... 24 #include "logging.h" 25 26 namespace open_vcdiff { 27 28 // This class is used by the decoder. It can use a standard or 29 // non-standard code table, and will translate the opcodes in the code table 30 // into delta instructions. 31 // 32 // NOT threadsafe. 33 // 34 class VCDiffCodeTableReader { 35 public: 36 // When constructed, the object will be set up to use the default code table. 37 // If a non-default code table is to be used, then UseCodeTable() 38 // should be called after the VCDiffCodeTableReader has been constructed. 39 // In any case, the Init() method must be called before GetNextInstruction() 40 // may be used. 41 // 42 VCDiffCodeTableReader(); 43 44 // Sets up a non-standard code table. The caller 45 // may free the memory occupied by the argument code table after 46 // passing it to this method, because the argument code table 47 // allocates space to store a copy of it. 48 // UseCodeTable() may be called either before or after calling Init(). 49 // Returns true if the code table was accepted, or false if the 50 // argument did not appear to be a valid code table. 51 // 52 bool UseCodeTable(const VCDiffCodeTableData& code_table_data, 53 unsigned char max_mode); 54 55 // Defines the buffer containing the instructions and sizes. 56 // This method must be called before GetNextInstruction() may be used. 57 // Init() may be called any number of times to reset the state of 58 // the object. 59 // Init(const char ** instructions_and_sizes,const char * instructions_and_sizes_end)60 void Init(const char** instructions_and_sizes, 61 const char* instructions_and_sizes_end) { 62 instructions_and_sizes_ = instructions_and_sizes; 63 instructions_and_sizes_end_ = instructions_and_sizes_end; 64 last_instruction_start_ = NULL; 65 pending_second_instruction_ = kNoOpcode; 66 last_pending_second_instruction_ = kNoOpcode; 67 } 68 69 // Updates the pointers to the buffer containing the instructions and sizes, 70 // but leaves the rest of the reader state intact, so that (for example) 71 // any pending second instruction or unread instruction will still be 72 // read when requested. NOTE: UnGetInstruction() will not work immediately 73 // after using UpdatePointers(); GetNextInstruction() must be called first. 74 // UpdatePointers(const char ** instructions_and_sizes,const char * instructions_and_sizes_end)75 void UpdatePointers(const char** instructions_and_sizes, 76 const char* instructions_and_sizes_end) { 77 instructions_and_sizes_ = instructions_and_sizes; 78 instructions_and_sizes_end_ = instructions_and_sizes_end; 79 last_instruction_start_ = *instructions_and_sizes; 80 // pending_second_instruction_ is unchanged 81 last_pending_second_instruction_ = pending_second_instruction_; 82 } 83 84 // Returns the next instruction from the stream of opcodes, 85 // or VCD_INSTRUCTION_END_OF_DATA if the end of the opcode stream is reached, 86 // or VCD_INSTRUCTION_ERROR if an error occurred. 87 // In the first of these cases, increments *instructions_and_sizes_ 88 // past the values it reads, and populates *size 89 // with the corresponding size for the returned instruction; 90 // otherwise, the value of *size is undefined, and is not 91 // guaranteed to be preserved. 92 // If the instruction returned is VCD_COPY, *mode will 93 // be populated with the copy mode; otherwise, the value of *mode 94 // is undefined, and is not guaranteed to be preserved. 95 // Any occurrences of VCD_NOOP in the opcode stream 96 // are skipped over and ignored, not returned. 97 // If Init() was not called before calling this method, then 98 // VCD_INSTRUCTION_ERROR will be returned. 99 // 100 VCDiffInstructionType GetNextInstruction(int32_t* size, unsigned char* mode); 101 102 // Puts a single instruction back onto the front of the 103 // instruction stream. The next call to GetNextInstruction() 104 // will return the same value that was returned by the last 105 // call. Calling UnGetInstruction() more than once before calling 106 // GetNextInstruction() will have no additional effect; you can 107 // only rewind one instruction. 108 // UnGetInstruction()109 void UnGetInstruction() { 110 if (last_instruction_start_) { 111 if (last_instruction_start_ > *instructions_and_sizes_) { 112 LOG(DFATAL) << "Internal error: last_instruction_start past end of " 113 "instructions_and_sizes in UnGetInstruction" << LOG_ENDL; 114 } 115 *instructions_and_sizes_ = last_instruction_start_; 116 if ((pending_second_instruction_ != kNoOpcode) && 117 (last_pending_second_instruction_ != kNoOpcode)) { 118 LOG(DFATAL) << "Internal error: two pending instructions in a row " 119 "in UnGetInstruction" << LOG_ENDL; 120 } 121 pending_second_instruction_ = last_pending_second_instruction_; 122 } 123 } 124 125 private: 126 // A pointer to the code table. This is the object that will be used 127 // to interpret opcodes in GetNextInstruction(). 128 const VCDiffCodeTableData* code_table_data_; 129 130 // If the default code table is not being used, then space for the 131 // code table data will be allocated using this pointer and freed 132 // when the VCDiffCodeTableReader is destroyed. This will keep the 133 // code that uses the object from having to worry about memory 134 // management for the non-standard code table, whose contents have 135 // been read as part of the encoded data file/stream. 136 // 137 std::auto_ptr<VCDiffCodeTableData> non_default_code_table_data_; 138 139 const char** instructions_and_sizes_; 140 const char* instructions_and_sizes_end_; 141 const char* last_instruction_start_; 142 OpcodeOrNone pending_second_instruction_; 143 OpcodeOrNone last_pending_second_instruction_; 144 145 // Making these private avoids implicit copy constructor & assignment operator 146 VCDiffCodeTableReader(const VCDiffCodeTableReader&); 147 void operator=(const VCDiffCodeTableReader&); 148 }; 149 150 }; // namespace open_vcdiff 151 152 #endif // OPEN_VCDIFF_DECODETABLE_H_ 153