Home | History | Annotate | Download | only in src
      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   //
     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_) {
    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