blob: f59fc1574bed3500179df067ca5353ae15fe837e [file] [log] [blame]
openvcdiff311c7142008-08-26 19:29:25 +00001// 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>
openvcdiff28db8072008-10-10 23:29:11 +000020#include <stddef.h> // NULL
openvcdiff311c7142008-08-26 19:29:25 +000021#include <stdint.h> // int32_t
openvcdiff311c7142008-08-26 19:29:25 +000022#include <memory> // auto_ptr
23#include "codetable.h" // VCDiffInstructi...
24#include "logging.h"
25
26namespace 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//
34class 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 //
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 //
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 //
109 void UnGetInstruction() {
110 if (last_instruction_start_) {
111 if (last_instruction_start_ > *instructions_and_sizes_) {
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000112 VCD_DFATAL << "Internal error: last_instruction_start past end of "
113 "instructions_and_sizes in UnGetInstruction" << VCD_ENDL;
openvcdiff311c7142008-08-26 19:29:25 +0000114 }
115 *instructions_and_sizes_ = last_instruction_start_;
116 if ((pending_second_instruction_ != kNoOpcode) &&
117 (last_pending_second_instruction_ != kNoOpcode)) {
openvcdiff@gmail.com732fff22010-08-04 18:00:00 +0000118 VCD_DFATAL << "Internal error: two pending instructions in a row "
119 "in UnGetInstruction" << VCD_ENDL;
openvcdiff311c7142008-08-26 19:29:25 +0000120 }
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_