1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2008 Google Inc.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Author: Lincoln Smith
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Licensed under the Apache License, Version 2.0 (the "License");
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// you may not use this file except in compliance with the License.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// You may obtain a copy of the License at
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//      http://www.apache.org/licenses/LICENSE-2.0
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unless required by applicable law or agreed to in writing, software
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distributed under the License is distributed on an "AS IS" BASIS,
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the License for the specific language governing permissions and
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limitations under the License.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef OPEN_VCDIFF_HEADERPARSER_H_
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define OPEN_VCDIFF_HEADERPARSER_H_
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <config.h>
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stddef.h>  // NULL
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdint.h>  // int32_t, uint32_t
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "checksum.h"  // VCDChecksum
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "vcdiff_defs.h"  // VCDiffResult
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace open_vcdiff {
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class contains a contiguous memory buffer with start and end pointers,
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// as well as a position pointer which shows how much of the buffer has been
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// parsed and how much remains.
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Because no virtual destructor is defined for ParseableChunk, a pointer to
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// a child class of ParseableChunk must be destroyed using its specific type,
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// rather than as a ParseableChunk*.
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ParseableChunk {
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ParseableChunk(const char* data_start, size_t data_size) {
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetDataBuffer(data_start, data_size);
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* End() const { return end_; }
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The number of bytes remaining to be parsed.  This is not necessarily the
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // same as the initial size of the buffer; it changes with each call to
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Advance().
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t UnparsedSize() const {
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return end_ - position_;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The number of bytes that have already been parsed.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t ParsedSize() const {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return position_ - start_;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool Empty() const { return 0 == UnparsedSize(); }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The start of the data remaining to be parsed.
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* UnparsedData() const { return position_; }
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns a pointer to the start of the data remaining to be parsed.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char** UnparsedDataAddr() { return &position_; }
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Moves the parsing position forward by number_of_bytes.
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Advance(size_t number_of_bytes);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Jumps the parsing position to a new location.
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetPosition(const char* position);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Jumps the parsing position to the end of the data chunk.
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Finish() {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    position_ = end_;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Jumps the parsing position so that there are now number_of_bytes
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // bytes left to parse.  This number should be smaller than the size of data
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to be parsed before the function was called.
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void FinishExcept(size_t number_of_bytes);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetDataBuffer(const char* data_start, size_t data_size) {
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    start_ = data_start;
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    end_ = data_start + data_size;
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    position_ = start_;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* start_;
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* end_;
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The current parsing position within the data chunk.
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Must always respect start_ <= position_ <= end_.
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* position_;
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Making these private avoids implicit copy constructor & assignment operator
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ParseableChunk(const ParseableChunk&);
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void operator=(const ParseableChunk&);
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Represents one of the three sections in the delta window, as described in
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RFC section 4.3:
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     * Data section for ADDs and RUNs
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     * Instructions and sizes section
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     * Addresses section for COPYs
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When using the interleaved format, data and addresses are pulled from the
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// instructions and sizes section rather than being stored in separate sections.
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For that reason, this class allows one DeltaWindowSection to be based on
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// another, such that the same position pointer is shared by both sections;
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// i.e., UnparsedDataAddr() returns the same value for both objects.
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// To achieve this end, one extra level of indirection (a pointer to a
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ParseableChunk object) is added.
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass DeltaWindowSection {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeltaWindowSection() : parseable_chunk_(NULL), owned_(true) { }
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~DeltaWindowSection() {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FreeChunk();
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Init(const char* data_start, size_t data_size) {
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (owned_ && parseable_chunk_) {
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Reuse the already-allocated ParseableChunk object.
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      parseable_chunk_->SetDataBuffer(data_start, data_size);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      parseable_chunk_ = new ParseableChunk(data_start, data_size);
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      owned_ = true;
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Init(DeltaWindowSection* original) {
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FreeChunk();
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parseable_chunk_ = original->parseable_chunk_;
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    owned_ = false;
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Invalidate() { FreeChunk(); }
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool IsOwned() const { return owned_; }
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The following functions just pass their arguments to the underlying
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseableChunk object.
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* End() const {
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->End();
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t UnparsedSize() const {
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->UnparsedSize();
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t ParsedSize() const {
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->ParsedSize();
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool Empty() const {
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->Empty();
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* UnparsedData() const {
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->UnparsedData();
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char** UnparsedDataAddr() {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->UnparsedDataAddr();
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Advance(size_t number_of_bytes) {
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_->Advance(number_of_bytes);
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void FreeChunk() {
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (owned_) {
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delete parseable_chunk_;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parseable_chunk_ = NULL;
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Will be NULL until Init() has been called.  If owned_ is true, this will
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // point to a ParseableChunk object that has been allocated with "new" and
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // must be deleted by this DeltaWindowSection object.  If owned_ is false,
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // this points at the parseable_chunk_ owned by a different DeltaWindowSection
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // object.  In this case, it is important to free the DeltaWindowSection which
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // does not own the ParseableChunk before (or simultaneously to) freeing the
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // DeltaWindowSection that owns it, or else deleted memory may be accessed.
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ParseableChunk* parseable_chunk_;
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool owned_;
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Making these private avoids implicit copy constructor & assignment operator
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeltaWindowSection(const DeltaWindowSection&);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void operator=(const DeltaWindowSection&);
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Used to parse the bytes and Varints that make up the delta file header
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// or delta window header.
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffHeaderParser {
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // header_start should be the start of the header to be parsed;
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // data_end is the position just after the last byte of available data
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (which may extend far past the end of the header.)
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffHeaderParser(const char* header_start, const char* data_end);
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // One of these functions should be called for each element of the header.
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // variable_description is a description of the value that we are attempting
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to parse, and will only be used to create descriptive error messages.
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the function returns true, then the element was parsed successfully
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // and its value has been placed in *value.  If the function returns false,
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // then *value is unchanged, and GetResult() can be called to return the
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // reason that the element could not be parsed, which will be either
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // RESULT_ERROR (an error occurred), or RESULT_END_OF_DATA (the limit data_end
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // was reached before the end of the element to be parsed.)  Once one of these
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // functions has returned false, further calls to any of the Parse...
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // functions will also return false without performing any additional actions.
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Typical usage is as follows:
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     int32_t segment_length = 0;
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     if (!header_parser.ParseInt32("segment length", &segment_length)) {
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //       return header_parser.GetResult();
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     }
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The following example takes advantage of the fact that calling a Parse...
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // function after an error or end-of-data condition is legal and does nothing.
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // It can thus parse more than one element in a row and check the status
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // afterwards.  If the first call to ParseInt32() fails, the second will have
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // no effect:
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     int32_t segment_length = 0, segment_position = 0;
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     header_parser.ParseInt32("segment length", &segment_length));
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     header_parser.ParseInt32("segment position", &segment_position));
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     if (RESULT_SUCCESS != header_parser.GetResult()) {
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //       return header_parser.GetResult();
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     }
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseByte(unsigned char* value);
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseInt32(const char* variable_description, int32_t* value);
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseUInt32(const char* variable_description, uint32_t* value);
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseChecksum(const char* variable_description, VCDChecksum* value);
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseSize(const char* variable_description, size_t* value);
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses the first three elements of the delta window header:
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Win_Indicator                            - byte
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     [Source segment size]                    - integer (VarintBE format)
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     [Source segment position]                - integer (VarintBE format)
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if the values were parsed successfully and the values were
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // found to be acceptable.  Returns false otherwise, in which case
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // GetResult() can be called to return the reason that the two values
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // could not be validated.  This will be either RESULT_ERROR (an error
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // occurred and was logged), or RESULT_END_OF_DATA (the limit data_end was
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // reached before the end of the values to be parsed.)  If return value is
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // true, then *win_indicator, *source_segment_length, and
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // *source_segment_position are populated with the parsed values.  Otherwise,
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the values of these output arguments are undefined.
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // dictionary_size: The size of the dictionary (source) file.  Used to
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     validate the limits of source_segment_length and
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     source_segment_position if the source segment is taken from the
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     dictionary (i.e., if the parsed *win_indicator equals VCD_SOURCE.)
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // decoded_target_size: The size of the target data that has been decoded
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     so far, including all target windows.  Used to validate the limits of
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     source_segment_length and source_segment_position if the source segment
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     is taken from the target (i.e., if the parsed *win_indicator equals
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     VCD_TARGET.)
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // allow_vcd_target: If this argument is false, and the parsed *win_indicator
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     is VCD_TARGET, then an error is produced; if true, VCD_TARGET is
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     allowed.
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // win_indicator (output): Points to a single unsigned char (not an array)
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     that will receive the parsed value of Win_Indicator.
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // source_segment_length (output): The parsed length of the source segment.
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // source_segment_position (output): The parsed zero-based index in the
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     source/target file from which the source segment is to be taken.
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseWinIndicatorAndSourceSegment(size_t dictionary_size,
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         size_t decoded_target_size,
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         bool allow_vcd_target,
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         unsigned char* win_indicator,
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         size_t* source_segment_length,
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         size_t* source_segment_position);
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses the following two elements of the delta window header:
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Length of the delta encoding             - integer (VarintBE format)
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Size of the target window                - integer (VarintBE format)
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Return conditions and values are the same as for
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseWinIndicatorAndSourceSegment(), above.
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseWindowLengths(size_t* target_window_length);
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // May only be called after ParseWindowLengths() has returned RESULT_SUCCESS.
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns a pointer to the end of the delta window (which might not point to
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // a valid memory location if there is insufficient input data.)
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* EndOfDeltaWindow() const;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses the following element of the delta window header:
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Delta_Indicator                          - byte
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Because none of the bits in Delta_Indicator are used by this implementation
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of VCDIFF, this function does not have an output argument to return the
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // value of that field.  It may return RESULT_SUCCESS, RESULT_ERROR, or
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // RESULT_END_OF_DATA as with the other Parse...() functions.
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseDeltaIndicator();
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses the following 3 elements of the delta window header:
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Length of data for ADDs and RUNs - integer (VarintBE format)
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Length of instructions and sizes - integer (VarintBE format)
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Length of addresses for COPYs    - integer (VarintBE format)
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If has_checksum is true, it also looks for the following element:
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     Adler32 checksum            - unsigned 32-bit integer (VarintBE format)
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Return conditions and values are the same as for
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseWinIndicatorAndSourceSegment(), above.
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseSectionLengths(bool has_checksum,
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           size_t* add_and_run_data_length,
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           size_t* instructions_and_sizes_length,
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           size_t* addresses_length,
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           VCDChecksum* checksum);
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If one of the Parse... functions returned false, this function
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // can be used to find the result code (RESULT_ERROR or RESULT_END_OF_DATA)
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // describing the reason for the most recent parse failure.  If none of the
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parse... functions has returned false, returns RESULT_SUCCESS.
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffResult GetResult() const {
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return return_code_;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The following functions just pass their arguments to the underlying
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseableChunk object.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* End() const {
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_.End();
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t UnparsedSize() const {
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_.UnparsedSize();
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t ParsedSize() const {
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_.ParsedSize();
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* UnparsedData() const {
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return parseable_chunk_.UnparsedData();
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parses two variable-length integers representing the source segment length
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // and source segment position (== offset.)  Checks whether the source segment
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // length and position would cause it to exceed the size of the source file or
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // target file.  Returns true if the values were parsed successfully and the
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // values were found to be acceptable.  Returns false otherwise, in which case
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // GetResult() can be called to return the reason that the two values could
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // not be validated, which will be either RESULT_ERROR (an error occurred and
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // was logged), or RESULT_END_OF_DATA (the limit data_end was reached before
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the end of the integers to be parsed.)
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // from_size: The requested size of the source segment.
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // from_boundary_name: A NULL-terminated string naming the end of the
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     source or target file, used in error messages.
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // from_name: A NULL-terminated string naming the source or target file,
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     also used in error messages.
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // source_segment_length (output): The parsed length of the source segment.
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // source_segment_position (output): The parsed zero-based index in the
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //     source/target file from which the source segment is to be taken.
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ParseSourceSegmentLengthAndPosition(size_t from_size,
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const char* from_boundary_name,
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const char* from_name,
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           size_t* source_segment_length,
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           size_t* source_segment_position);
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ParseableChunk parseable_chunk_;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Contains the result code of the last Parse...() operation that failed
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (RESULT_ERROR or RESULT_END_OF_DATA).  If no Parse...() method has been
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // called, or if all calls to Parse...() were successful, then this contains
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // RESULT_SUCCESS.
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffResult return_code_;
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Will be zero until ParseWindowLengths() has been called.  After
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseWindowLengths() has been called successfully, this contains the
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // parsed length of the delta encoding.
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t delta_encoding_length_;
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Will be NULL until ParseWindowLengths() has been called.  After
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ParseWindowLengths() has been called successfully, this points to the
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // beginning of the section of the current window titled "The delta encoding"
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // in the RFC, i.e., to the position just after the length of the delta
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // encoding.
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* delta_encoding_start_;
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Making these private avoids implicit copy constructor & assignment operator
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffHeaderParser(const VCDiffHeaderParser&);
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void operator=(const VCDiffHeaderParser&);
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace open_vcdiff
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // OPEN_VCDIFF_HEADERPARSER_H_
401