• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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