1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Use of this source code is governed by a BSD-style license that can be
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// found in the LICENSE file.
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// The main idea in Courgette is to do patching *under a tranformation*.  The
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// input is transformed into a new representation, patching occurs in the new
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// repesentation, and then the tranform is reversed to get the patched data.
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen//
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// The idea is applied to pieces (or 'Elements') of the whole (or 'Ensemble').
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Each of the elements has to go through the same set of steps in lock-step,
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// but there may be many different kinds of elements, which have different
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// transformation.
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen//
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// This file declares all the main types involved in creating and applying a
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// patch with this structure.
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#ifndef COURGETTE_ENSEMBLE_H_
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#define COURGETTE_ENSEMBLE_H_
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include <vector>
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include <string>
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "base/basictypes.h"
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "courgette/courgette.h"
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "courgette/region.h"
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen#include "courgette/streams.h"
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogennamespace courgette {
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// Forward declarations:
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass Ensemble;
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// An Element is a region of an Ensemble with an identifyable kind.
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen//
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass Element {
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public:
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Element(ExecutableType kind,
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen          Ensemble* ensemble,
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen          const Region& region);
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual ~Element();
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  ExecutableType kind() const { return kind_; }
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  const Region& region() const { return region_; }
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // The name is used only for debugging and logging.
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  virtual std::string Name() const;
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // Returns the byte position of this Element relative to the start of
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // containing Ensemble.
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  size_t offset_in_ensemble() const;
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private:
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  ExecutableType kind_;
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Ensemble* ensemble_;
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Region region_;
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  DISALLOW_COPY_AND_ASSIGN(Element);
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen};
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass Ensemble {
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public:
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Ensemble(const Region& region, const char* name)
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      : region_(region), name_(name) {}
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  ~Ensemble();
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  const Region& region() const { return region_; }
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  const std::string& name() const { return name_; }
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // Scans the region to find Elements within the region().
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Status FindEmbeddedElements();
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  // Returns the elements found by 'FindEmbeddedElements'.
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  const std::vector<Element*>& elements() const { return elements_; }
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private:
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  Region region_;       // The memory, owned by caller, containing the
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        // Ensemble's data.
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  std::string name_;    // A debugging/logging name for the Ensemble.
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  std::vector<Element*> elements_;        // Embedded elements discovered.
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  std::vector<Element*> owned_elements_;  // For deallocation.
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  DISALLOW_COPY_AND_ASSIGN(Ensemble);
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen};
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogeninline size_t Element::offset_in_ensemble() const {
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen  return region().start() - ensemble_->region().start();
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// The 'CourgettePatchFile' is class is a 'namespace' for the constants that
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// appear in a Courgette patch file.
96struct CourgettePatchFile {
97  //
98  // The Courgette patch format interleaves the data for N embedded Elements.
99  //
100  // Format of a patch file:
101  //  header:
102  //    magic
103  //    version
104  //    source-checksum
105  //    target-checksum
106  //    final-patch-input-size (an allocation hint)
107  //  multiple-streams:
108  //    stream 0:
109  //      number-of-transformed-elements (N) - varint32
110  //      transformation-1-method-id
111  //      transformation-2-method-id
112  //      ...
113  //      transformation-1-initial-parameters
114  //      transformation-2-initial-parameters
115  //      ...
116  //    stream 1:
117  //      correction:
118  //        transformation-1-parameters
119  //        transformation-2-parameters
120  //        ...
121  //    stream 2:
122  //      correction:
123  //        transformed-element-1
124  //        transformed-element-2
125  //        ...
126  //    stream 3:
127  //      correction:
128  //        base-file
129  //        element-1
130  //        element-2
131  //        ...
132
133  static const uint32 kMagic = 'C' | ('o' << 8) | ('u' << 16);
134
135  static const uint32 kVersion = 20110216;
136};
137
138// For any transform you would implement both a TransformationPatcher and a
139// TransformationPatchGenerator.
140//
141// TransformationPatcher is the interface which abstracts out the actual
142// transformation used on an Element.  The patching itself happens outside the
143// actions of a TransformationPatcher.  There are four steps.
144//
145// The first step is an Init step.  The parameters to the Init step identify the
146// element, for example, range of locations within the original ensemble that
147// correspond to the element.
148//
149// PredictTransformParameters, explained below.
150//
151// The two final steps are 'Transform' - to transform the element into a new
152// representation, and to 'Reform' - to transform from the new representation
153// back to the original form.
154//
155// The Transform step takes some parameters.  This allows the transform to be
156// customized to the particular element, or to receive some assistance in the
157// analysis required to perform the transform.  The transform parameters might
158// be extensive but mostly predicable, so preceeding Transform is a
159// PredictTransformParameters step.
160//
161class TransformationPatcher {
162 public:
163  virtual ~TransformationPatcher() {}
164
165  // First step: provides parameters for the patching.  This would at a minimum
166  // identify the element within the ensemble being patched.
167  virtual Status Init(SourceStream* parameter_stream) = 0;
168
169  // Second step: predicts transform parameters.
170  virtual Status PredictTransformParameters(
171      SinkStreamSet* predicted_parameters) = 0;
172
173  // Third step: transforms element from original representation into alternate
174  // representation.
175  virtual Status Transform(SourceStreamSet* corrected_parameters,
176                           SinkStreamSet* transformed_element) = 0;
177
178  // Final step: transforms element back from alternate representation into
179  // original representation.
180  virtual Status Reform(SourceStreamSet* transformed_element,
181                        SinkStream* reformed_element) = 0;
182};
183
184// TransformationPatchGenerator is the interface which abstracts out the actual
185// transformation used (and adjustment used) when differentially compressing one
186// Element from the |new_ensemble| against a corresponding element in the
187// |old_ensemble|.
188//
189// This is not a pure interface.  There is a small amount of inheritance
190// implementation for the fields and actions common to all
191// TransformationPatchGenerators.
192//
193// When TransformationPatchGenerator is subclassed, there will be a
194// corresponding subclass of TransformationPatcher.
195//
196class TransformationPatchGenerator {
197 public:
198  TransformationPatchGenerator(Element* old_element,
199                               Element* new_element,
200                               TransformationPatcher* patcher);
201
202  virtual ~TransformationPatchGenerator();
203
204  // Returns the TransformationMethodId that identies this transformation.
205  virtual ExecutableType Kind() = 0;
206
207  // Writes the parameters that will be passed to TransformationPatcher::Init.
208  virtual Status WriteInitialParameters(SinkStream* parameter_stream) = 0;
209
210  // Predicts the transform parameters for the |old_element|.  This must match
211  // exactly the output that will be produced by the PredictTransformParameters
212  // method of the corresponding subclass of TransformationPatcher.  This method
213  // is not pure. The default implementation delegates to the patcher to
214  // guarantee matching output.
215  virtual Status PredictTransformParameters(SinkStreamSet* prediction);
216
217  // Writes the desired parameters for the transform of the old element from the
218  // file representation to the alternate representation.
219  virtual Status CorrectedTransformParameters(SinkStreamSet* parameters) = 0;
220
221  // Writes both |old_element| and |new_element| in the new representation.
222  // |old_corrected_parameters| will match the |corrected_parameters| passed to
223  // the Transform method of the corresponding sublcass of
224  // TransformationPatcher.
225  //
226  // The output written to |old_transformed_element| must match exactly the
227  // output written by the Transform method of the corresponding subclass of
228  // TransformationPatcher.
229  virtual Status Transform(SourceStreamSet* old_corrected_parameters,
230                           SinkStreamSet* old_transformed_element,
231                           SinkStreamSet* new_transformed_element) = 0;
232
233  // Transforms the new transformed_element back from the alternate
234  // representation into the original file format.  This must match exactly the
235  // output that will be produced by the corresponding subclass of
236  // TransformationPatcher::Reform.  This method is not pure. The default
237  // implementation delegates to the patcher.
238  virtual Status Reform(SourceStreamSet* transformed_element,
239                        SinkStream* reformed_element);
240
241 protected:
242  Element* old_element_;
243  Element* new_element_;
244  TransformationPatcher* patcher_;
245};
246
247}  // namespace
248#endif  // COURGETTE_ENSEMBLE_H_
249